< Summary

Line coverage
39%
Covered lines: 4223
Uncovered lines: 6367
Coverable lines: 10590
Total lines: 15049
Line coverage: 39.8%
Branch coverage
37%
Covered branches: 2582
Total branches: 6918
Branch coverage: 37.3%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity Line coverage
File 1: get_AllowedToDependOnAllocationState()0%60%
File 1: get_Kind()0%40%
File 1: .ctor(...)100%1100%
File 1: .ctor(...)100%10%
File 1: Microsoft.Dafny.IASTVisitorContext.get_EnclosingModule()100%1100%
File 1: .ctor(...)100%1100%
File 1: GetContext(...)100%1100%
File 1: VisitOneStatement(...)33.33%1240%
File 1: VisitTopLevelFrameExpression(...)100%10%
File 1: DesugarFunctionsInFrameClause(...)100%10%
File 1: FrameArrowToObjectSet(...)0%100%
File 1: VisitExpression(...)50%257.14%
File 1: VisitOneExpression(...)5.55%368.88%
File 1: DiscoverBestBounds_MultipleVars(...)0%40%
File 1: DiscoverBestBounds_MultipleVars_AllowReordering(...)0%260%
File 1: DiscoverAllBounds_Aux_MultipleVars(...)0%40%
File 1: DiscoverAllBounds_SingleVar(...)100%10%
File 1: DiscoverAllBounds_Aux_SingleVar(...)0%1020%
File 1: DiscoverBoundsFunctionCallExpr(...)0%40%
File 1: NormalizedConjuncts()0%860%
File 1: SanitizeForBoundDiscovery(...)0%540%
File 1: IsMonotonic(...)0%120%
File 2: ResolveNamesAndInferTypes(...)100%4100%
File 2: ResolveNamesAndInferTypesForOneDeclarationInitial(...)62.5%857.57%
File 2: ResolveNamesAndInferTypesForOneDeclaration(...)66.66%1856.52%
File 2: EagerAddAssignableConstraint(...)0%40%
File 2: AddAssignableConstraint(...)100%1100%
File 2: AddXConstraint(...)100%1100%
File 2: AddAssignableConstraint(...)100%1100%
File 2: AddXConstraint(...)100%1100%
File 2: AddXConstraint(...)100%1100%
File 2: AddXConstraint(...)100%1100%
File 2: AddXConstraint(...)100%1100%
File 2: PrintTypeConstraintState(...)12.5%1623.52%
File 2: SolveAllTypeConstraints()20%1043.47%
File 2: ResolveAttributes(...)91.66%1283.33%
File 2: ResolveExpression(...)38.96%30840.86%
File 2: ResolveTypeParameters(...)80%1082.35%
File 2: ConstrainSubtypeRelation(...)100%1100%
File 2: ConstrainTypeExprBool(...)100%1100%
File 2: ConstrainSubtypeRelation(...)100%1100%
File 2: ConstrainAssignable(...)78.57%1490.47%
File 2: ConstrainAssignableTypeArgs(...)92.85%1491.89%
File 2: ConstrainSubtypeRelation_Equal(...)87.5%1677.77%
File 2: ConstrainSubtypeRelation(...)100%12100%
File 2: ConstrainSubtypeRelation_Aux(...)91.66%1291.66%
File 2: DetermineRootLeaf(...)75.92%5470%
File 2: .ctor(...)100%1100%
File 2: AssignProxyAndHandleItsConstraints(...)50%277.77%
File 2: AssignProxyAndHandleItsConstraints_aux(...)67.39%4659.37%
File 2: ImposeSubtypingConstraint(...)80%2086.66%
File 2: ConstrainTypeHead_Recursive(...)16.66%650%
File 2: ConstrainTypeHead(...)53.16%7964.7%
File 2: KeepConstraints(...)88.88%2783.33%
File 2: .ctor(...)100%1100%
File 2: ToString()0%40%
File 2: Confirm(...)61.32%51258.35%
File 2: ProxyWithNoSubTypeConstraint(...)100%10100%
File 2: CouldBeAnything()100%10%
File 2: FindCollectionType(...)16.66%1833.33%
File 2: .ctor(...)100%1100%
File 2: .ctor(...)100%1100%
File 2: PartiallySolveTypeConstraints(...)59.55%17858.84%
File 2: NewIntegerBasedProxy(...)100%1100%
File 2: ContainsAsTypeParameter(...)0%140%
File 2: AddAllProxies(...)100%4100%
File 2: ProcessAssignable(...)70.83%2459.37%
File 2: ConvertAssignableToSubtypeConstraints(...)100%14100%
File 2: TightenUpEquatable(...)80%1082.35%
File 2: ProcessOneSubtypingConstraintAndItsSubs(...)95%2096.15%
File 2: ProcessFullStrength_SubDirection(...)90%10100%
File 2: ProcessFullStrength_SuperDirection(...)100%10100%
File 2: AssignKnownEnd(...)67.85%2874.35%
File 2: AssignKnownEndsFullstrength(...)36.66%3033.33%
File 2: AssignKnownEndsFullstrength_SubDirection(...)80.76%2684.21%
File 2: CloseOverAssignableRhss(...)78.57%1476.47%
File 2: HasApplicableNullableRefTypeConstraint(...)50%658.33%
File 2: HasApplicableNullableRefTypeConstraint_SubDirection(...)100%6100%
File 2: HasApplicableNullableRefTypeConstraint_SubDirection_aux(...)40%1061.53%
File 2: AssignKnownEndsFullstrength_SuperDirection(...)86.66%3084.61%
File 2: Reaches(...)50%277.77%
File 2: Reaches_aux(...)83.33%1887.5%
File 2: ResolveClassMemberBodiesInitial(...)33.33%1242.1%
File 2: ResolveClassMemberBodies(...)45.45%2254.76%
File 2: ResolveCtorTypes(...)41.66%1262.5%
File 2: ResolveCtorSignature(...)100%2100%
File 2: AddDatatypeDependencyEdge(...)83.33%680%
File 2: ResolveFrameExpressionTopLevel(...)100%10%
File 2: ResolveFrameExpression(...)0%140%
File 2: ResolveIterator(...)0%240%
File 2: CheckIsLvalue(...)23.07%2638.7%
File 2: ResolveBlockStatement(...)37.5%847.05%
File 2: ResolveStatementWithLabels(...)12.5%825%
File 2: ResolveAlternatives(...)0%140%
File 2: ResolveCallStmt(...)50%3663.33%
File 2: ResolveActualParameters(...)37.09%6252.13%
File 2: GetLocationInformation(...)83.33%6100%
File 2: ResolveDotSuffix_Type(...)0%260%
File 2: CreateResolver_IdentifierExpr(...)75%1677.77%
File 2: ResolveStatement(...)39.36%28241.83%
File 2: ResolveLoopSpecificationComponents(...)58.33%1271.42%
File 2: ResolveParameterDefaultValues(...)44.44%1841.66%
File 2: ResolveType(...)100%1100%
File 2: ResolveType(...)100%1100%
File 2: ResolveType(...)100%1100%
File 2: ResolveType(...)100%1100%
File 2: .ctor(...)100%10%
File 2: ResolveTypeLenient(...)63.15%7661.26%
File 2: FillInTypeArguments(...)81.25%1690.9%
File 2: TypeConstraintsIncludeProxy(...)100%1100%
File 2: TypeConstraintsIncludeProxy_Aux(...)22.22%1844%
File 2: ResolveTypeRhs(...)19.11%6824%
File 2: ResolveMember(...)62.5%2456.52%
File 2: PartiallyResolveTypeForMemberSelection(...)45.91%9843.57%
File 2: GetBaseTypeFromProxy(...)83.33%1872.72%
File 2: GetBaseTypeFromProxy_Eq(...)100%2100%
File 2: GetBaseTypeFromProxy_EqAux(...)12.5%1621.73%
File 2: GetRelatedTypeProxies(...)65.62%3264%
File 2: JoinOfAllSubtypes(...)55.55%3675.67%
File 2: MeetOfAllSupertypes(...)65.62%3264.44%
File 2: CheckVariance(...)52.63%3862.74%
File 2: ConstrainToIntegerType(...)100%2100%
File 2: ResolveDatatypeUpdate(...)0%220%
File 2: DesugarDatatypeUpdate(...)0%160%
File 2: ResolveNameSegment(...)100%1100%
File 2: ResolveNameSegment(...)35.93%6438.14%
File 2: ResolveDatatypeConstructor(...)50%1453.33%
File 2: ResolveNameSegment_Type(...)71.42%1477.41%
File 2: ResolveDotSuffix(...)35.36%8241.6%
File 2: CheckForAmbiguityInShadowedImportedModule(...)50%433.33%
File 2: NameConflictsWithModuleContents(...)0%100%
File 2: ResolveExprDotCall(...)45.83%4861.76%
File 2: ResolveApplySuffix(...)25.8%6230.69%
File 2: ResolveDatatypeValue(...)43.75%1670%
File 2: ResolveFunctionCallExpr(...)0%300%
File 2: ResolveReceiver(...)0%40%
File 2: ResolveSeqSelectExpr(...)87.5%896.77%
File 3: get_Options()100%1100%
File 3: .ctor(...)100%176.92%
File 3: get_Reporter()100%1100%
File 3: get_TypeConstraintErrorsToBeReported()100%1100%
File 3: RevealedInScope(...)0%20%
File 3: VisibleInScope(...)100%2100%
File 3: FreshTempVarName(...)0%20%
File 3: Create(...)0%100%
File 3: Name(...)0%40%
File 3: ModuleNames(...)0%40%
File 3: Create(...)0%20%
File 3: Equals(...)0%40%
File 3: GetHashCode(...)0%20%
File 3: get_WhatKind()100%10%
File 3: .ctor(...)100%10%
File 3: Microsoft.Dafny.Resolver.IAmbiguousThing<Microsoft.Dafny.TopLevelDecl>.get_Pool()100%10%
File 3: ModuleNames()100%10%
File 3: Create(...)0%20%
File 3: Equals(...)100%10%
File 3: GetHashCode(...)100%10%
File 3: get_WhatKind()100%10%
File 3: .ctor(...)100%10%
File 3: Microsoft.Dafny.Resolver.IAmbiguousThing<Microsoft.Dafny.MemberDecl>.get_Pool()100%10%
File 3: ModuleNames()100%10%
File 3: .ctor(...)100%4100%
File 3: AddRotateMember(...)100%1100%
File 3: ObjectInvariant()100%10%
File 3: AsValuetypeDecl(...)75%485.71%
File 3: CheckDupModuleNames(...)62.5%876.47%
File 3: ResolveProgram(...)65.54%14874.18%
File 3: ResolveValuetypeDecls()87.5%878.57%
File 3: ResolveModuleDefinition(...)29.16%2456.25%
File 3: ResolveModuleExport(...)10.89%15614.54%
File 3: CheckModuleExportConsistency(...)3.57%2810%
File 3: .ctor(...)100%1100%
File 3: BindName(...)50%287.5%
File 3: TryLookup(...)100%10%
File 3: TryLookupFilter(...)0%60%
File 3: get_ModuleList()100%10%
File 3: SubBindings(...)100%10%
File 3: BindModuleNames(...)28.12%3224.56%
File 3: ShortenPrefix(...)100%10%
File 3: BindModuleName_LiteralModuleDecl(...)0%80%
File 3: ResolveQualifiedModuleIdRootRefines(...)100%10%
File 3: ResolveQualifiedModuleIdRootImport(...)0%60%
File 3: ResolveQualifiedModuleIdRootAbstract(...)0%60%
File 3: ProcessDependenciesDefinition(...)20%2024.13%
File 3: ProcessDependencies(...)20%1030%
File 3: ModuleNotFoundErrorMessage(...)0%20%
File 3: EquivIfPresent(...)50%280%
File 3: MergeSignature(...)60%2064.28%
File 3: ResolveOpenedImports(...)50%1644.44%
File 3: ResolveAlias(...)0%20%
File 3: ResolveOpenedImportsWorker(...)0%360%
File 3: RegisterTopLevelDecls(...)68.88%9074.68%
File 3: RegisterMembers(...)26.47%3414.49%
File 3: RegisterByMethod(...)0%40%
File 3: MakeAbstractSignature(...)0%100%
File 3: CloneDeclaration(...)0%20%
File 3: ResolveModuleQualifiedId(...)0%120%
File 3: ResolveExport(...)0%180%
File 3: RevealAllInScope(...)100%12100%
File 3: ResolveTopLevelDecls_Signatures(...)57.69%5261.03%
File 3: .cctor()100%10%
File 3: ResolveTopLevelDecls_Core(...)51.01%39448.44%
File 3: FillInPostConditionsAndBodiesOfPrefixLemmas(...)2.94%342.5%
File 3: CheckIsOkayWithoutRHS(...)0%120%
File 3: ResolveClassMembers_Pass1(...)50%3247.61%
File 3: CheckForUnnecessaryEqualitySupportDeclarations(...)25%437.5%
File 3: CheckParameterDefaultValuesAreCompilable(...)12.5%837.5%
File 3: ReportCallGraphCycleError(...)100%10%
File 3: ReportCycleError(...)100%10%
File 3: MaxBV(...)100%10%
File 3: MaxBV(...)100%10%
File 3: FigureOutNativeType(...)0%4670%
File 3: CheckOlderParameters(...)0%100%
File 3: CheckExpression(...)100%1100%
File 3: CheckExpression(...)100%1100%
File 3: .ctor(...)100%1100%
File 3: VisitOneExpr(...)25%830.76%
File 3: VisitOneStmt(...)50%1245.45%
File 3: CheckForFuelAdjustments(...)3.57%2814.81%
File 3: .ctor(...)100%1100%
File 3: .ctor(...)100%1100%
File 3: VisitOneStmt(...)100%1100%
File 3: Invert(...)0%40%
File 3: .ctor(...)100%10%
File 3: VisitOneExpr(...)0%520%
File 3: KNatMismatchError(...)0%60%
File 3: .ctor(...)100%10%
File 3: VisitOneExpr(...)0%180%
File 3: VisitOneStmt(...)0%40%
File 3: ExtremePredicateChecks(...)100%10%
File 3: .ctor(...)100%10%
File 3: VisitOneStmt(...)0%80%
File 3: VisitOneExpr(...)0%40%
File 3: ExtremeLemmaChecks(...)100%10%
File 3: ExtremeLemmaChecks(...)0%20%
File 3: CheckTypeCharacteristics_Stmt(...)100%1100%
File 3: CheckTypeCharacteristics_Expr(...)100%1100%
File 3: CheckTypeCharacteristics_Type(...)100%1100%
File 3: .ctor(...)100%1100%
File 3: VisitOneStmt(...)62.5%5664.44%
File 3: VisitOneExpr(...)52.7%7440%
File 3: VisitType(...)60%3077.77%
File 3: CheckTypeInstantiation(...)50%672.72%
File 3: CheckCharacteristics(...)46.66%3042.3%
File 3: TypeEqualityErrorMessageHint(...)0%60%
File 3: CanCompareWith(...)6.25%1620%
File 3: ComputeGhostInterest(...)100%1100%
File 3: .ctor(...)100%1100%
File 3: VisitOneStmt(...)75%466.66%
File 3: .ctor(...)100%1100%
File 3: VisitOneStmt(...)10%1015%
File 3: .ctor(...)100%1100%
File 3: CheckInit(...)100%10%
File 3: CheckInit(...)0%80%
File 3: VisitExpr(...)100%10%
File 3: VisitOneExpr(...)0%100%
File 3: LiberalRHSVisit(...)0%240%
File 3: IsThisDotField(...)0%20%
File 3: IsCollectionOperator(...)0%100%
File 3: InferRequiredEqualitySupport(...)50%3272.22%
File 3: ResolveParentTraitTypes(...)4.54%2229.62%
File 3: RegisterInheritedMembers(...)12.5%4815.94%
File 3: ResolveClassMemberTypes(...)33.33%2435.29%
File 3: InheritedTraitMembers(...)7.89%7610%
File 3: CheckOverride_FunctionParameters(...)0%120%
File 3: CheckOverride_MethodParameters(...)0%100%
File 3: CheckOverride_TypeParameters(...)0%160%
File 3: CheckOverride_ResolvedParameters(...)0%300%
File 3: SccStratosphereCheck(...)42.85%1464%
File 3: ComputeGroundingCtor(...)94.44%1895.83%
File 3: CheckCanBeConstructed(...)50%3661.22%
File 3: DetermineEqualitySupport(...)61.29%6261.53%
File 3: IsRecognizedAttribute(...)0%500%
File 3: ScopePushAndReport(...)100%1100%
File 3: ScopePushAndReport(...)50%455.55%
File 3: ResolveFunctionSignature(...)62.5%877.77%
File 3: DisallowNonGhostFieldSpecifiers(...)0%40%
File 3: ResolveMethodSignature(...)87.5%887.5%
File 3: ResolveIteratorSignature(...)0%160%
File 3: ObjectInvariant()100%10%
File 3: .ctor(...)100%1100%
File 3: .ctor(...)100%1100%
File 3: ResolvedArrayType(...)100%1100%
File 3: FillInDefaultLoopDecreases(...)4.67%1074.13%
File 3: VarDotMethod(...)100%10%
File 3: makeTemp(...)100%10%
File 3: EnsureSupportsErrorHandling(...)0%200%
File 3: CheckLocalityUpdates(...)0%260%
File 3: CheckLocalityUpdatesLhs(...)0%40%
File 3: .ctor(...)100%10%
File 3: ToString()0%20%
File 3: FindAllMembers(...)100%2100%
File 3: GetThisType(...)50%466.66%
File 3: GetReceiverType(...)100%10%
File 3: ResolveDominatingLabelInExpr(...)0%60%
File 3: VarDotFunction(...)100%10%
File 3: LetPatIn(...)100%10%
File 3: LetVarIn(...)100%10%
File 3: ResolveLetOrFailExpr(...)0%20%
File 3: SelectAppropriateArrowTypeForFunction(...)100%10%
File 3: SelectAppropriateArrowType(...)0%40%
File 3: ConstrainToIntegerType(...)100%1100%
File 3: ResolveNestedMatchExpr(...)100%1100%
File 3: ResolveCasePattern(...)0%500%
File 3: FillInDefaultValueExpressions()50%271.42%
File 3: FillInDefaultValueExpression(...)0%40%
File 3: .ctor(...)100%10%
File 3: Substitute(...)0%20%
File 3: BuildTypeArgumentSubstitute(...)62.5%873.33%
File 3: AddParentTypeParameterSubstitutions(...)70%1075%
File 3: GhostPrefix(...)50%2100%
File 3: GetSignatureExt(...)0%40%
File 3: GetSignature(...)100%10%
File 3: GetImpliedTypeConstraint(...)100%1100%
File 3: GetImpliedTypeConstraint(...)50%860%
File 3: FreeVariables(...)0%340%
File 3: .cctor()100%1100%
File 3: get_Msg()0%80%
File 3: .ctor(...)100%1100%
File 3: ResolveOp(...)85.71%10587.7%
File 3: CollectFriendlyCallsInExtremeLemmaSpecification(...)0%20%
File 3: .ctor(...)100%10%
File 3: VisitOneExpr(...)0%280%
File 4: get_IsPrefixPredicate()100%1100%
File 4: get_IsExtremePredicate()100%10%
File 4: get_IsPrefixDeclaration()50%2100%
File 4: .ctor(...)100%1100%
File 4: Microsoft.Dafny.IASTVisitorContext.get_EnclosingModule()100%1100%
File 4: get_reporter()100%10%
File 4: .ctor(...)100%1100%
File 4: GetContext(...)100%1100%
File 4: VisitOneDeclaration(...)55%2046.66%
File 4: VisitField(...)50%257.14%
File 4: VisitOneStatement(...)50%244.44%
File 4: PostVisitOneStatement(...)58.33%1252.17%
File 4: PostVisitOneExpression(...)36.41%17334.9%
File 4: VisitExtendedPattern(...)100%4100%
File 4: IsDetermined(...)100%2100%
File 4: CheckTypeIsDetermined(...)100%4100%
File 4: CheckTypeArgsContainNoOrdinal(...)50%2100%
File 4: CheckContainsNoOrdinal(...)50%271.42%

File(s)

/home/ubuntu/dafny-verifier/src/main/dafny_compiler/dafny/Source/DafnyCore/Resolver/BoundsDiscovery.cs

#LineLine coverage
 1//-----------------------------------------------------------------------------
 2//
 3// Copyright by the contributors to the Dafny Project
 4// SPDX-License-Identifier: MIT
 5//
 6//-----------------------------------------------------------------------------
 7using System.Collections.Generic;
 8using System.Linq;
 9using System.Diagnostics.Contracts;
 10using Microsoft.Boogie;
 11
 12namespace Microsoft.Dafny {
 13  public partial class Resolver {
 14    private class BoundsDiscoveryVisitor : ASTVisitor<BoundsDiscoveryVisitor.BoundsDiscoveryContext> {
 15      public class BoundsDiscoveryContext : IASTVisitorContext {
 16        private readonly IASTVisitorContext astVisitorContext;
 17        readonly bool inLambdaExpression;
 18
 19        public bool AllowedToDependOnAllocationState =>
 020          !(astVisitorContext is Function or ConstantField or RedirectingTypeDecl || inLambdaExpression);
 21
 22        public string Kind {
 023          get {
 24            // assumes context denotes a lambda expression, redirecting type, or member declaration
 025            if (inLambdaExpression) {
 026              return "lambda expression";
 27            }
 28            string kind;
 029            if (astVisitorContext is RedirectingTypeDecl redirectingTypeDecl) {
 030              kind = redirectingTypeDecl.WhatKind;
 031            } else {
 032              var memberDecl = (MemberDecl)astVisitorContext;
 033              kind = memberDecl.WhatKind;
 034            }
 035            return $"{kind} definition";
 036          }
 37        }
 38
 589639        public BoundsDiscoveryContext(IASTVisitorContext astVisitorContext) {
 294840          this.astVisitorContext = astVisitorContext;
 294841          this.inLambdaExpression = false;
 294842        }
 43
 44        /// <summary>
 45        /// This constructor is used to say that, within parentContext, the context is inside a lambda
 46        /// expression.
 47        /// </summary>
 048        public BoundsDiscoveryContext(BoundsDiscoveryContext parentContext, LambdaExpr lambdaExpr) {
 049          this.astVisitorContext = parentContext.astVisitorContext;
 050          this.inLambdaExpression = true;
 051        }
 52
 196053        ModuleDefinition IASTVisitorContext.EnclosingModule => astVisitorContext.EnclosingModule;
 54      }
 55
 56      private readonly ErrorReporter reporter;
 57
 63258      public BoundsDiscoveryVisitor(ErrorReporter reporter) {
 31659        this.reporter = reporter;
 31660      }
 61
 294862      public override BoundsDiscoveryContext GetContext(IASTVisitorContext astVisitorContext, bool inFunctionPostconditi
 294863        return new BoundsDiscoveryContext(astVisitorContext);
 294864      }
 65
 15762266      protected override bool VisitOneStatement(Statement stmt, BoundsDiscoveryContext context) {
 15762267        if (stmt is ForallStmt forallStmt) {
 068          forallStmt.Bounds = DiscoverBestBounds_MultipleVars(forallStmt.BoundVars, forallStmt.Range, true);
 069          if (forallStmt.Body == null) {
 070            reporter.Warning(MessageSource.Resolver, ErrorRegistry.NoneId, forallStmt.Tok, "note, this forall statement 
 071          }
 15762272        } else if (stmt is AssignSuchThatStmt assignSuchThatStmt) {
 073          if (assignSuchThatStmt.AssumeToken == null) {
 074            var varLhss = new List<IVariable>();
 075            foreach (var lhs in assignSuchThatStmt.Lhss) {
 076              var ide = (IdentifierExpr)lhs.Resolved;  // successful resolution implies all LHS's are IdentifierExpr's
 077              varLhss.Add(ide.Var);
 078            }
 079            assignSuchThatStmt.Bounds = DiscoverBestBounds_MultipleVars(varLhss, assignSuchThatStmt.Expr, true);
 080          }
 15829281        } else if (stmt is OneBodyLoopStmt oneBodyLoopStmt) {
 67082          oneBodyLoopStmt.ComputeBodySurrogate(reporter);
 67083        }
 84
 15762285        return base.VisitOneStatement(stmt, context);
 15762286      }
 87
 088      public override void VisitTopLevelFrameExpression(FrameExpression frameExpression, BoundsDiscoveryContext context)
 089        DesugarFunctionsInFrameClause(frameExpression);
 090        base.VisitTopLevelFrameExpression(frameExpression, context);
 091      }
 92
 093      void DesugarFunctionsInFrameClause(FrameExpression frameExpression) {
 094        frameExpression.DesugaredExpression = FrameArrowToObjectSet(frameExpression.E);
 095      }
 96
 97      /// <summary>
 98      /// The motivation for this method is to convert a reads-clause frame expression "f.reads" into a set.
 99      /// More generally, if the given expression "e" has type "X ~> collection<Y>", for some list of type X,
 100      /// some reference type Y, and "collection" being "set", "iset", "seq", or "multiset", then this method
 101      /// returns an expression of type "set<Y>" denoting
 102      ///
 103      ///     UNION x: X :: e(x)                      // e.g., UNION x: X :: f.reads(x)
 104      ///
 105      /// For example, if "e" is an expression "f.reads" of type "X ~> set<object>", then the expression
 106      /// returned is the union of "f.reads(x)" over all inputs "x" to "f".
 107      ///
 108      /// If the type of "e" is not of the form "X ~> collection<Y>" as stated above, then this method simply
 109      /// returns the given "e".
 110      ///
 111      /// Dafny does not have a UNION comprehension, so the expression returned has the form
 112      ///
 113      ///     { obj: Y | exists x: X :: obj in e(x) }
 114      ///
 115      /// which in Dafny notation is written
 116      ///
 117      ///     set x: X, obj: Y | obj in e(x) :: obj
 118      ///
 119      /// Note, since Y is a reference type and there is, at any one time, only a finite number of references,
 120      /// the result type is finite.
 121      ///
 122      /// Note: A pending improvement would be to limit the range of the set comprehension to the values for x
 123      /// that satisfy e's precondition.
 124      /// </summary>
 0125      public static Expression FrameArrowToObjectSet(Expression e) {
 126        Contract.Requires(e != null);
 0127        var arrowType = e.Type.AsArrowType;
 0128        if (arrowType == null) {
 0129          return e;
 130        }
 0131        var collectionType = arrowType.Result.AsCollectionType;
 0132        if (collectionType == null || collectionType.NormalizeExpand() is MapType) {
 0133          return e;
 134        }
 0135        var elementType = collectionType.Arg; // "elementType" is called "Y" in the description of this method, above
 0136        if (!elementType.IsRefType) {
 0137          return e;
 138        }
 139
 0140        var boundVarDecls = new List<BoundVar>();
 0141        var boundVarUses = new List<Expression>();
 0142        var i = 0;
 0143        foreach (var functionArgumentType in arrowType.Args) {
 0144          var bv = new BoundVar(e.tok, $"_x{i}", functionArgumentType);
 0145          boundVarDecls.Add(bv);
 0146          boundVarUses.Add(new IdentifierExpr(e.tok, bv.Name) { Type = bv.Type, Var = bv });
 0147          i++;
 0148        }
 0149        var objVar = new BoundVar(e.tok, "_obj", elementType);
 0150        var objUse = new IdentifierExpr(e.tok, objVar.Name) { Type = objVar.Type, Var = objVar };
 0151        boundVarDecls.Add(objVar);
 152
 0153        var collection = new ApplyExpr(e.tok, e, boundVarUses, e.tok) {
 0154          Type = collectionType
 0155        };
 0156        var resolvedOpcode = collectionType.ResolvedOpcodeForIn;
 157
 0158        var inCollection = new BinaryExpr(e.tok, BinaryExpr.Opcode.In, objUse, collection) {
 0159          ResolvedOp = resolvedOpcode,
 0160          Type = Type.Bool
 0161        };
 162
 0163        var attributes = new Attributes("_reads", new List<Expression>(), null);
 0164        return new SetComprehension(e.tok, e.RangeToken, true, boundVarDecls, inCollection, objUse, attributes) {
 0165          Type = new SetType(true, elementType)
 0166        };
 0167      }
 168
 732688169      protected override void VisitExpression(Expression expr, BoundsDiscoveryContext context) {
 732688170        if (expr is LambdaExpr lambdaExpr) {
 0171          lambdaExpr.Reads.Iter(DesugarFunctionsInFrameClause);
 172
 173          // Make the context more specific when visiting inside a lambda expression
 0174          context = new BoundsDiscoveryContext(context, lambdaExpr);
 0175        }
 732688176        base.VisitExpression(expr, context);
 732688177      }
 178
 732688179      protected override bool VisitOneExpression(Expression expr, BoundsDiscoveryContext context) {
 732688180        if (expr is ComprehensionExpr and not LambdaExpr) {
 0181          var e = (ComprehensionExpr)expr;
 182          // apply bounds discovery to quantifiers, finite sets, and finite maps
 0183          Expression whereToLookForBounds = null;
 0184          var polarity = true;
 0185          if (e is QuantifierExpr quantifierExpr) {
 0186            whereToLookForBounds = quantifierExpr.LogicalBody();
 0187            polarity = quantifierExpr is ExistsExpr;
 0188          } else if (e is SetComprehension setComprehension) {
 0189            whereToLookForBounds = setComprehension.Range;
 0190          } else if (e is MapComprehension) {
 0191            whereToLookForBounds = e.Range;
 0192          } else {
 0193            Contract.Assert(false);  // otherwise, unexpected ComprehensionExpr
 0194          }
 0195          if (whereToLookForBounds != null) {
 0196            e.Bounds = DiscoverBestBounds_MultipleVars_AllowReordering(e.BoundVars, whereToLookForBounds, polarity);
 0197            if (2 <= reporter.Options.Allocated && !context.AllowedToDependOnAllocationState) {
 0198              foreach (var bv in ComprehensionExpr.BoundedPool.MissingBounds(e.BoundVars, e.Bounds,
 0199                         ComprehensionExpr.BoundedPool.PoolVirtues.IndependentOfAlloc)) {
 0200                var how = Attributes.Contains(e.Attributes, "_reads") ? "(implicitly by using a function in a reads clau
 0201                var message =
 0202                  $"a {e.WhatKind} involved in a {context.Kind} {how}is not allowed to depend on the set of allocated re
 0203                  $" but values of '{bv.Name}' (of type '{bv.Type}') may contain references";
 0204                if (bv.Type.IsTypeParameter || bv.Type.IsAbstractType) {
 0205                  message += $" (perhaps declare its type as '{bv.Type}(!new)')";
 0206                }
 0207                message += " (see documentation for 'older' parameters)";
 0208                reporter.Error(MessageSource.Resolver, e, message);
 0209              }
 0210            }
 211
 0212            if ((e as SetComprehension)?.Finite == true || (e as MapComprehension)?.Finite == true) {
 213              // the comprehension had better produce a finite set
 0214              if (e.Type.HasFinitePossibleValues) {
 215                // This means the set is finite, regardless of if the Range is bounded.  So, we don't give any error her
 216                // However, if this expression is used in a non-ghost context (which is not yet known at this stage of
 217                // resolution), the resolver will generate an error about that later.
 0218              } else {
 219                // we cannot be sure that the set/map really is finite
 0220                foreach (var bv in ComprehensionExpr.BoundedPool.MissingBounds(e.BoundVars, e.Bounds, ComprehensionExpr.
 0221                  reporter.Error(MessageSource.Resolver, e,
 0222                    "the result of a {0} must be finite, but Dafny's heuristics can't figure out how to produce a bounde
 0223                    e.WhatKind, bv.Name);
 0224                }
 0225              }
 0226            }
 0227          }
 228
 0229        }
 230
 732688231        return base.VisitOneExpression(expr, context);
 732688232      }
 233    }
 234
 235    /// <summary>
 236    /// For a list of variables "bvars", returns a list of best bounds for each respective variable.
 237    /// If no bound is found for a variable "v", then the bound for "v" in the returned list is set to "null".
 238    /// </summary>
 239    public static List<ComprehensionExpr.BoundedPool> DiscoverBestBounds_MultipleVars<VT>(List<VT> bvars, Expression exp
 0240      bool polarity) where VT : IVariable {
 241      Contract.Requires(bvars != null);
 242      Contract.Requires(expr != null);
 243      Contract.Ensures(Contract.Result<List<ComprehensionExpr.BoundedPool>>() != null);
 0244      foreach (var bv in bvars) {
 0245        var c = GetImpliedTypeConstraint(bv, bv.Type);
 0246        expr = polarity ? Expression.CreateAnd(c, expr) : Expression.CreateImplies(c, expr);
 0247      }
 0248      var bests = DiscoverAllBounds_Aux_MultipleVars(bvars, expr, polarity);
 0249      return bests;
 0250    }
 251
 252    public static List<ComprehensionExpr.BoundedPool> DiscoverBestBounds_MultipleVars_AllowReordering<VT>(List<VT> bvars
 0253      bool polarity) where VT : IVariable {
 254      Contract.Requires(bvars != null);
 255      Contract.Requires(expr != null);
 256      Contract.Ensures(Contract.Result<List<ComprehensionExpr.BoundedPool>>() != null);
 0257      var bounds = DiscoverBestBounds_MultipleVars(bvars, expr, polarity);
 0258      if (bvars.Count > 1) {
 259        // It may be helpful to try all permutations (or, better yet, to use an algorithm that keeps track of the depend
 260        // and discovers good bounds more efficiently). However, all permutations would be expensive. Therefore, we try 
 261        // other permutation, namely the reversal "bvars". This covers the important case where there are two bound vari
 262        // that work out in the opposite order. It also covers one more case for the (probably rare) case of there being
 263        // than two bound variables.
 0264        var bvarsMissyElliott = new List<VT>(bvars);  // make a copy
 0265        bvarsMissyElliott.Reverse();  // and then flip it and reverse it, Ti esrever dna ti pilf nwod gnaht ym tup I
 0266        var boundsMissyElliott = DiscoverBestBounds_MultipleVars(bvarsMissyElliott, expr, polarity);
 267        // Figure out which one seems best
 0268        var meBetter = 0;
 0269        for (int i = 0; i < bvars.Count; i++) {
 0270          var orig = bounds[i];
 0271          var me = boundsMissyElliott[i];
 0272          if (orig == null && me != null) {
 0273            meBetter = 1; break; // end game
 0274          } else if (orig != null && me == null) {
 0275            meBetter = -1; break; // end game
 0276          } else if (orig != null && me != null) {
 0277            if ((orig.Virtues & ComprehensionExpr.BoundedPool.PoolVirtues.Finite) != 0) { meBetter--; }
 0278            if ((orig.Virtues & ComprehensionExpr.BoundedPool.PoolVirtues.Enumerable) != 0) { meBetter--; }
 0279            if ((me.Virtues & ComprehensionExpr.BoundedPool.PoolVirtues.Finite) != 0) { meBetter++; }
 0280            if ((me.Virtues & ComprehensionExpr.BoundedPool.PoolVirtues.Enumerable) != 0) { meBetter++; }
 0281          }
 0282        }
 0283        if (meBetter > 0) {
 284          // yes, this reordering seems to have been better
 0285          bvars.Reverse();
 0286          return boundsMissyElliott;
 287        }
 0288      }
 0289      return bounds;
 0290    }
 291
 292    private static List<ComprehensionExpr.BoundedPool> DiscoverAllBounds_Aux_MultipleVars<VT>(List<VT> bvars, Expression
 0293      bool polarity) where VT : IVariable {
 294      Contract.Requires(bvars != null);
 295      Contract.Requires(expr != null);
 296      Contract.Ensures(Contract.Result<List<ComprehensionExpr.BoundedPool>>() != null);
 297      Contract.Ensures(Contract.Result<List<ComprehensionExpr.BoundedPool>>().Count == bvars.Count);
 0298      var knownBounds = new List<ComprehensionExpr.BoundedPool>();
 0299      for (var j = 0; j < bvars.Count; j++) {
 0300        knownBounds.Add(null);
 0301      }
 302      // Note, in the following loop, it's important to go backwards, because DiscoverAllBounds_Aux_SingleVar assumes "k
 303      // filled in for higher-indexed variables.
 0304      for (var j = bvars.Count; 0 <= --j;) {
 0305        var bounds = DiscoverAllBounds_Aux_SingleVar(bvars, j, expr, polarity, knownBounds);
 0306        knownBounds[j] = ComprehensionExpr.BoundedPool.GetBest(bounds);
 307#if DEBUG_PRINT
 308        if (knownBounds[j] is ComprehensionExpr.IntBoundedPool) {
 309          var ib = (ComprehensionExpr.IntBoundedPool)knownBounds[j];
 310          var lo = ib.LowerBound == null ? "" : Printer.ExprToString(ib.LowerBound);
 311          var hi = ib.UpperBound == null ? "" : Printer.ExprToString(ib.UpperBound);
 312          Console.WriteLine("DEBUG: Bound for var {3}, {0}:  {1} .. {2}", bvars[j].Name, lo, hi, j);
 313        } else if (knownBounds[j] is ComprehensionExpr.SetBoundedPool) {
 314          Console.WriteLine("DEBUG: Bound for var {2}, {0}:  in {1}", bvars[j].Name, Printer.ExprToString(((Comprehensio
 315        } else {
 316          Console.WriteLine("DEBUG: Bound for var {2}, {0}:  {1}", bvars[j].Name, knownBounds[j], j);
 317        }
 318#endif
 0319      }
 0320      return knownBounds;
 0321    }
 322
 0323    public static List<ComprehensionExpr.BoundedPool> DiscoverAllBounds_SingleVar<VT>(VT v, Expression expr) where VT : 
 0324      expr = Expression.CreateAnd(GetImpliedTypeConstraint(v, v.Type), expr);
 0325      return DiscoverAllBounds_Aux_SingleVar(new List<VT> { v }, 0, expr, true, new List<ComprehensionExpr.BoundedPool>(
 0326    }
 327
 328    /// <summary>
 329    /// Returns a list of (possibly partial) bounds for "bvars[j]", each of which can be written without mentioning any 
 330    /// that is not bounded.
 331    /// </summary>
 332    private static List<ComprehensionExpr.BoundedPool> DiscoverAllBounds_Aux_SingleVar<VT>(List<VT> bvars, int j, Expres
 0333      bool polarity, List<ComprehensionExpr.BoundedPool> knownBounds) where VT : IVariable {
 334      Contract.Requires(bvars != null);
 335      Contract.Requires(0 <= j && j < bvars.Count);
 336      Contract.Requires(expr != null);
 337      Contract.Requires(knownBounds != null);
 338      Contract.Requires(knownBounds.Count == bvars.Count);
 0339      var bv = bvars[j];
 0340      var bounds = new List<ComprehensionExpr.BoundedPool>();
 341
 342      // Maybe the type itself gives a bound
 0343      if (bv.Type.IsBoolType) {
 0344        bounds.Add(new ComprehensionExpr.BoolBoundedPool());
 0345      } else if (bv.Type.IsCharType) {
 0346        bounds.Add(new ComprehensionExpr.CharBoundedPool());
 0347      } else if (bv.Type.IsDatatype && bv.Type.AsDatatype.HasFinitePossibleValues) {
 0348        bounds.Add(new ComprehensionExpr.DatatypeBoundedPool(bv.Type.AsDatatype));
 0349      } else if (bv.Type.IsNumericBased(Type.NumericPersuasion.Int)) {
 0350        bounds.Add(new AssignSuchThatStmt.WiggleWaggleBound());
 0351      } else if (!bv.Type.MayInvolveReferences) {
 0352        bounds.Add(new ComprehensionExpr.AllocFreeBoundedPool(bv.Type));
 0353      }
 354
 355      // Go through the conjuncts of the range expression to look for bounds.
 0356      foreach (var conjunct in NormalizedConjuncts(expr, polarity)) {
 0357        if (conjunct is IdentifierExpr) {
 0358          var ide = (IdentifierExpr)conjunct;
 0359          if (ide.Var == (IVariable)bv) {
 0360            Contract.Assert(bv.Type.IsBoolType);
 0361            bounds.Add(new ComprehensionExpr.ExactBoundedPool(Expression.CreateBoolLiteral(Token.NoToken, true)));
 0362          }
 0363          continue;
 364        }
 0365        if (conjunct is UnaryOpExpr || conjunct is OldExpr) {
 366          // we also consider a unary expression sitting immediately inside an old
 0367          var unary = conjunct as UnaryOpExpr ?? ((OldExpr)conjunct).E.Resolved as UnaryOpExpr;
 0368          if (unary != null) {
 0369            var ide = unary.E.Resolved as IdentifierExpr;
 0370            if (ide != null && ide.Var == (IVariable)bv) {
 0371              if (unary.ResolvedOp == UnaryOpExpr.ResolvedOpcode.BoolNot) {
 0372                bounds.Add(new ComprehensionExpr.ExactBoundedPool(Expression.CreateBoolLiteral(Token.NoToken, false)));
 0373              } else if (unary.ResolvedOp == UnaryOpExpr.ResolvedOpcode.Allocated) {
 0374                bounds.Add(new ComprehensionExpr.ExplicitAllocatedBoundedPool());
 0375              }
 0376            }
 0377          }
 0378          continue;
 379        }
 0380        if (conjunct is FunctionCallExpr functionCallExpr) {
 0381          DiscoverBoundsFunctionCallExpr(functionCallExpr, bv, bounds);
 0382          continue;
 383        }
 0384        var c = conjunct as BinaryExpr;
 0385        if (c == null) {
 386          // other than what we already covered above, we only know what to do with binary expressions
 0387          continue;
 388        }
 0389        var e0 = c.E0;
 0390        var e1 = c.E1;
 0391        int whereIsBv = SanitizeForBoundDiscovery(bvars, j, c.ResolvedOp, knownBounds, ref e0, ref e1);
 0392        if (whereIsBv < 0) {
 0393          continue;
 394        }
 0395        switch (c.ResolvedOp) {
 396          case BinaryExpr.ResolvedOpcode.InSet:
 0397            if (whereIsBv == 0) {
 0398              bounds.Add(new ComprehensionExpr.SetBoundedPool(e1, e0.Type, e1.Type.AsSetType.Arg, e1.Type.AsSetType.Fini
 0399            }
 0400            break;
 401          case BinaryExpr.ResolvedOpcode.Subset:
 0402            if (whereIsBv == 0) {
 0403              bounds.Add(new ComprehensionExpr.SubSetBoundedPool(e1, e1.Type.AsSetType.Finite));
 0404            } else {
 0405              bounds.Add(new ComprehensionExpr.SuperSetBoundedPool(e0));
 0406            }
 0407            break;
 408          case BinaryExpr.ResolvedOpcode.InMultiSet:
 0409            if (whereIsBv == 0) {
 0410              bounds.Add(new ComprehensionExpr.MultiSetBoundedPool(e1, e0.Type, e1.Type.AsMultiSetType.Arg));
 0411            }
 0412            break;
 413          case BinaryExpr.ResolvedOpcode.InSeq:
 0414            if (whereIsBv == 0 && e1.Type.AsSeqType is { } seqType) {
 0415              bounds.Add(new ComprehensionExpr.SeqBoundedPool(e1, e0.Type, seqType.Arg));
 0416            }
 0417            break;
 418          case BinaryExpr.ResolvedOpcode.InMap:
 0419            if (whereIsBv == 0) {
 0420              bounds.Add(new ComprehensionExpr.MapBoundedPool(e1, e0.Type, e1.Type.AsMapType.Arg, e1.Type.AsMapType.Fini
 0421            }
 0422            break;
 423          case BinaryExpr.ResolvedOpcode.EqCommon:
 424          case BinaryExpr.ResolvedOpcode.SetEq:
 425          case BinaryExpr.ResolvedOpcode.SeqEq:
 426          case BinaryExpr.ResolvedOpcode.MultiSetEq:
 427          case BinaryExpr.ResolvedOpcode.MapEq:
 0428            var otherOperand = whereIsBv == 0 ? e1 : e0;
 0429            bounds.Add(new ComprehensionExpr.ExactBoundedPool(otherOperand));
 0430            break;
 431          case BinaryExpr.ResolvedOpcode.Gt:
 432          case BinaryExpr.ResolvedOpcode.Ge:
 0433            Contract.Assert(false);
 0434            throw new cce.UnreachableException(); // promised by postconditions of NormalizedConjunct
 435          case BinaryExpr.ResolvedOpcode.Lt:
 0436            if (e0.Type.IsNumericBased(Type.NumericPersuasion.Int)) {
 0437              if (whereIsBv == 0) {
 438                // bv < E
 0439                bounds.Add(new ComprehensionExpr.IntBoundedPool(null, e1));
 0440              } else {
 441                // E < bv
 0442                bounds.Add(new ComprehensionExpr.IntBoundedPool(Expression.CreateIncrement(e0, 1), null));
 0443              }
 0444            }
 0445            break;
 446          case BinaryExpr.ResolvedOpcode.Le:
 0447            if (e0.Type.IsNumericBased(Type.NumericPersuasion.Int)) {
 0448              if (whereIsBv == 0) {
 449                // bv <= E
 0450                bounds.Add(new ComprehensionExpr.IntBoundedPool(null, Expression.CreateIncrement(e1, 1)));
 0451              } else {
 452                // E <= bv
 0453                bounds.Add(new ComprehensionExpr.IntBoundedPool(e0, null));
 0454              }
 0455            }
 0456            break;
 457          case BinaryExpr.ResolvedOpcode.RankLt:
 0458            if (whereIsBv == 0) {
 0459              bounds.Add(new ComprehensionExpr.DatatypeInclusionBoundedPool(e0.Type.IsIndDatatype));
 0460            }
 0461            break;
 462          case BinaryExpr.ResolvedOpcode.RankGt:
 0463            if (whereIsBv == 1) {
 0464              bounds.Add(new ComprehensionExpr.DatatypeInclusionBoundedPool(e1.Type.IsIndDatatype));
 0465            }
 0466            break;
 467          default:
 0468            break;
 469        }
 0470      }
 0471      return bounds;
 0472    }
 473
 474    private static void DiscoverBoundsFunctionCallExpr<VT>(FunctionCallExpr fce, VT boundVariable, List<ComprehensionExp
 0475      where VT : IVariable {
 476      Contract.Requires(fce != null);
 477      Contract.Requires(boundVariable != null);
 478      Contract.Requires(bounds != null);
 479
 0480      var formals = fce.Function.Formals;
 0481      Contract.Assert(formals.Count == fce.Args.Count);
 0482      if (LinqExtender.Zip(formals, fce.Args).Any(t => t.Item1.IsOlder && t.Item2.Resolved is IdentifierExpr ide && ide.
 0483        bounds.Add(new ComprehensionExpr.OlderBoundedPool());
 0484        return;
 485      }
 0486    }
 487
 488    /// <summary>
 489    /// Returns all conjuncts of "expr" in "polarity" positions.  That is, if "polarity" is "true", then
 490    /// returns the conjuncts of "expr" in positive positions; else, returns the conjuncts of "expr" in
 491    /// negative positions.  The method considers a canonical-like form of the expression that pushes
 492    /// negations inwards far enough that one can determine what the result is going to be (so, almost
 493    /// a negation normal form).
 494    /// As a convenience, arithmetic inequalities are rewritten so that the negation of an arithmetic
 495    /// inequality is never returned and the comparisons > and >= are never returned; the negation of
 496    /// a common equality or disequality is rewritten analogously.
 497    /// Requires "expr" to be successfully resolved.
 498    /// Ensures that what is returned is not a ConcreteSyntaxExpression.
 499    /// </summary>
 0500    static IEnumerable<Expression> NormalizedConjuncts(Expression expr, bool polarity) {
 501      // We consider 5 cases.  To describe them, define P(e)=Conjuncts(e,true) and N(e)=Conjuncts(e,false).
 502      //   *  X ==> Y    is treated as a shorthand for !X || Y, and so is described by the remaining cases
 503      //   *  X && Y     P(_) = P(X),P(Y)    and    N(_) = !(X && Y)
 504      //   *  X || Y     P(_) = (X || Y)     and    N(_) = N(X),N(Y)
 505      //   *  !X         P(_) = N(X)         and    N(_) = P(X)
 506      //   *  else       P(_) = else         and    N(_) = !else
 507      // So for ==>, we have:
 508      //   *  X ==> Y    P(_) = P(!X || Y) = (!X || Y) = (X ==> Y)
 509      //                 N(_) = N(!X || Y) = N(!X),N(Y) = P(X),N(Y)
 0510      expr = expr.Resolved;
 511
 512      // Binary expressions
 0513      var b = expr as BinaryExpr;
 0514      if (b != null) {
 0515        bool breakDownFurther = false;
 0516        bool p0 = polarity;
 0517        switch (b.ResolvedOp) {
 518          case BinaryExpr.ResolvedOpcode.And:
 0519            breakDownFurther = polarity;
 0520            break;
 521          case BinaryExpr.ResolvedOpcode.Or:
 0522            breakDownFurther = !polarity;
 0523            break;
 524          case BinaryExpr.ResolvedOpcode.Imp:
 0525            breakDownFurther = !polarity;
 0526            p0 = !p0;
 0527            break;
 528          default:
 0529            break;
 530        }
 0531        if (breakDownFurther) {
 0532          foreach (var c in NormalizedConjuncts(b.E0, p0)) {
 0533            yield return c;
 0534          }
 0535          foreach (var c in NormalizedConjuncts(b.E1, polarity)) {
 0536            yield return c;
 0537          }
 0538          yield break;
 539        }
 0540      }
 541
 542      // Unary expression
 0543      var u = expr as UnaryOpExpr;
 0544      if (u != null && u.Op == UnaryOpExpr.Opcode.Not) {
 0545        foreach (var c in NormalizedConjuncts(u.E, !polarity)) {
 0546          yield return c;
 0547        }
 0548        yield break;
 549      }
 550
 551      // no other case applied, so return the expression or its negation, but first clean it up a little
 0552      b = expr as BinaryExpr;
 0553      if (b != null) {
 554        BinaryExpr.Opcode newOp;
 555        BinaryExpr.ResolvedOpcode newROp;
 556        bool swapOperands;
 0557        switch (b.ResolvedOp) {
 558          case BinaryExpr.ResolvedOpcode.Gt:  // A > B         yield polarity ? (B < A) : (A <= B);
 0559            newOp = polarity ? BinaryExpr.Opcode.Lt : BinaryExpr.Opcode.Le;
 0560            newROp = polarity ? BinaryExpr.ResolvedOpcode.Lt : BinaryExpr.ResolvedOpcode.Le;
 0561            swapOperands = polarity;
 0562            break;
 563          case BinaryExpr.ResolvedOpcode.Ge:  // A >= B        yield polarity ? (B <= A) : (A < B);
 0564            newOp = polarity ? BinaryExpr.Opcode.Le : BinaryExpr.Opcode.Lt;
 0565            newROp = polarity ? BinaryExpr.ResolvedOpcode.Le : BinaryExpr.ResolvedOpcode.Lt;
 0566            swapOperands = polarity;
 0567            break;
 568          case BinaryExpr.ResolvedOpcode.Le:  // A <= B        yield polarity ? (A <= B) : (B < A);
 0569            newOp = polarity ? BinaryExpr.Opcode.Le : BinaryExpr.Opcode.Lt;
 0570            newROp = polarity ? BinaryExpr.ResolvedOpcode.Le : BinaryExpr.ResolvedOpcode.Lt;
 0571            swapOperands = !polarity;
 0572            break;
 573          case BinaryExpr.ResolvedOpcode.Lt:  // A < B         yield polarity ? (A < B) : (B <= A);
 0574            newOp = polarity ? BinaryExpr.Opcode.Lt : BinaryExpr.Opcode.Le;
 0575            newROp = polarity ? BinaryExpr.ResolvedOpcode.Lt : BinaryExpr.ResolvedOpcode.Le;
 0576            swapOperands = !polarity;
 0577            break;
 578          case BinaryExpr.ResolvedOpcode.EqCommon:  // A == B         yield polarity ? (A == B) : (A != B);
 0579            newOp = polarity ? BinaryExpr.Opcode.Eq : BinaryExpr.Opcode.Neq;
 0580            newROp = polarity ? BinaryExpr.ResolvedOpcode.EqCommon : BinaryExpr.ResolvedOpcode.NeqCommon;
 0581            swapOperands = false;
 0582            break;
 583          case BinaryExpr.ResolvedOpcode.NeqCommon:  // A != B         yield polarity ? (A != B) : (A == B);
 0584            newOp = polarity ? BinaryExpr.Opcode.Neq : BinaryExpr.Opcode.Eq;
 0585            newROp = polarity ? BinaryExpr.ResolvedOpcode.NeqCommon : BinaryExpr.ResolvedOpcode.EqCommon;
 0586            swapOperands = false;
 0587            break;
 588          case BinaryExpr.ResolvedOpcode.NotInSet:  // A !in B         yield polarity ? (A !in B) : (A in B);
 0589            newOp = polarity ? BinaryExpr.Opcode.NotIn : BinaryExpr.Opcode.In;
 0590            newROp = polarity ? BinaryExpr.ResolvedOpcode.NotInSet : BinaryExpr.ResolvedOpcode.InSet;
 0591            swapOperands = false;
 0592            break;
 593          case BinaryExpr.ResolvedOpcode.NotInSeq:  // A !in B         yield polarity ? (A !in B) : (A in B);
 0594            newOp = polarity ? BinaryExpr.Opcode.NotIn : BinaryExpr.Opcode.In;
 0595            newROp = polarity ? BinaryExpr.ResolvedOpcode.NotInSeq : BinaryExpr.ResolvedOpcode.InSeq;
 0596            swapOperands = false;
 0597            break;
 598          case BinaryExpr.ResolvedOpcode.NotInMultiSet:  // A !in B         yield polarity ? (A !in B) : (A in B);
 0599            newOp = polarity ? BinaryExpr.Opcode.NotIn : BinaryExpr.Opcode.In;
 0600            newROp = polarity ? BinaryExpr.ResolvedOpcode.NotInMultiSet : BinaryExpr.ResolvedOpcode.InMultiSet;
 0601            swapOperands = false;
 0602            break;
 603          case BinaryExpr.ResolvedOpcode.NotInMap:  // A !in B         yield polarity ? (A !in B) : (A in B);
 0604            newOp = polarity ? BinaryExpr.Opcode.NotIn : BinaryExpr.Opcode.In;
 0605            newROp = polarity ? BinaryExpr.ResolvedOpcode.NotInMap : BinaryExpr.ResolvedOpcode.InMap;
 0606            swapOperands = false;
 0607            break;
 608          default:
 0609            goto JUST_RETURN_IT;
 610        }
 0611        if (newROp != b.ResolvedOp || swapOperands) {
 0612          b = new BinaryExpr(b.tok, newOp, swapOperands ? b.E1 : b.E0, swapOperands ? b.E0 : b.E1);
 0613          b.ResolvedOp = newROp;
 0614          b.Type = Type.Bool;
 0615          yield return b;
 0616          yield break;
 617        }
 0618      }
 0619    JUST_RETURN_IT:;
 0620      if (polarity) {
 0621        yield return expr;
 0622      } else {
 0623        expr = new UnaryOpExpr(expr.tok, UnaryOpExpr.Opcode.Not, expr);
 0624        expr.Type = Type.Bool;
 0625        yield return expr;
 0626      }
 0627    }
 628
 629    /// <summary>
 630    /// If the return value is negative, the resulting "e0" and "e1" should not be used.
 631    /// Otherwise, the following is true on return:
 632    /// The new "e0 op e1" is equivalent to the old "e0 op e1".
 633    /// One of "e0" and "e1" is the identifier "boundVars[bvi]"; the return value is either 0 or 1, and indicates which.
 634    /// The other of "e0" and "e1" is an expression whose free variables are not among "boundVars[bvi..]".
 635    /// Ensures that the resulting "e0" and "e1" are not ConcreteSyntaxExpression's.
 636    /// </summary>
 637    static int SanitizeForBoundDiscovery<VT>(List<VT> boundVars, int bvi, BinaryExpr.ResolvedOpcode op,
 638      List<ComprehensionExpr.BoundedPool> knownBounds,
 0639      ref Expression e0, ref Expression e1) where VT : IVariable {
 640      Contract.Requires(boundVars != null);
 641      Contract.Requires(0 <= bvi && bvi < boundVars.Count);
 642      Contract.Requires(knownBounds != null);
 643      Contract.Requires(knownBounds.Count == boundVars.Count);
 644      Contract.Requires(e0 != null);
 645      Contract.Requires(e1 != null);
 646      Contract.Ensures(Contract.Result<int>() < 2);
 647      Contract.Ensures(!(Contract.ValueAtReturn(out e0) is ConcreteSyntaxExpression));
 648      Contract.Ensures(!(Contract.ValueAtReturn(out e1) is ConcreteSyntaxExpression));
 649
 0650      IVariable bv = boundVars[bvi];
 0651      e0 = e0.Resolved;
 0652      e1 = e1.Resolved;
 653
 654      // make an initial assessment of where bv is; to continue, we need bv to appear in exactly one operand
 0655      var fv0 = FreeVariables(e0);
 0656      var fv1 = FreeVariables(e1);
 657      Expression thisSide;
 658      Expression thatSide;
 659      int whereIsBv;
 0660      if (fv0.Contains(bv)) {
 0661        if (fv1.Contains(bv)) {
 0662          return -1;
 663        }
 0664        whereIsBv = 0;
 0665        thisSide = e0;
 0666        thatSide = e1;
 0667      } else if (fv1.Contains(bv)) {
 0668        whereIsBv = 1;
 0669        thisSide = e1;
 0670        thatSide = e0;
 0671      } else {
 0672        return -1;
 673      }
 674
 675      // Next, clean up the side where bv is by adjusting both sides of the expression
 0676      switch (op) {
 677        case BinaryExpr.ResolvedOpcode.EqCommon:
 678        case BinaryExpr.ResolvedOpcode.NeqCommon:
 679        case BinaryExpr.ResolvedOpcode.Gt:
 680        case BinaryExpr.ResolvedOpcode.Ge:
 681        case BinaryExpr.ResolvedOpcode.Le:
 682        case BinaryExpr.ResolvedOpcode.Lt:
 683          // Repeatedly move additive or subtractive terms from thisSide to thatSide
 0684          while (true) {
 0685            var bin = thisSide as BinaryExpr;
 0686            if (bin == null) {
 0687              break; // done simplifying
 688
 0689            } else if (bin.ResolvedOp == BinaryExpr.ResolvedOpcode.Add) {
 690              // Change "A+B op C" into either "A op C-B" or "B op C-A", depending on where we find bv among A and B.
 0691              if (!FreeVariables(bin.E1).Contains(bv)) {
 0692                thisSide = bin.E0.Resolved;
 0693                thatSide = new BinaryExpr(bin.tok, BinaryExpr.Opcode.Sub, thatSide, bin.E1);
 0694              } else if (!FreeVariables(bin.E0).Contains(bv)) {
 0695                thisSide = bin.E1.Resolved;
 0696                thatSide = new BinaryExpr(bin.tok, BinaryExpr.Opcode.Sub, thatSide, bin.E0);
 0697              } else {
 0698                break; // done simplifying
 699              }
 0700              ((BinaryExpr)thatSide).ResolvedOp = BinaryExpr.ResolvedOpcode.Sub;
 0701              thatSide.Type = bin.Type;
 702
 0703            } else if (bin.ResolvedOp == BinaryExpr.ResolvedOpcode.Sub) {
 704              // Change "A-B op C" in a similar way.
 0705              if (!FreeVariables(bin.E1).Contains(bv)) {
 706                // change to "A op C+B"
 0707                thisSide = bin.E0.Resolved;
 0708                thatSide = new BinaryExpr(bin.tok, BinaryExpr.Opcode.Add, thatSide, bin.E1);
 0709                ((BinaryExpr)thatSide).ResolvedOp = BinaryExpr.ResolvedOpcode.Add;
 0710              } else if (!FreeVariables(bin.E0).Contains(bv)) {
 711                // In principle, change to "-B op C-A" and then to "B dualOp A-C".  But since we don't want
 712                // to change "op", we instead end with "A-C op B" and switch the mapping of thisSide/thatSide
 713                // to e0/e1 (by inverting "whereIsBv").
 0714                thisSide = bin.E1.Resolved;
 0715                thatSide = new BinaryExpr(bin.tok, BinaryExpr.Opcode.Sub, bin.E0, thatSide);
 0716                ((BinaryExpr)thatSide).ResolvedOp = BinaryExpr.ResolvedOpcode.Sub;
 0717                whereIsBv = 1 - whereIsBv;
 0718              } else {
 0719                break; // done simplifying
 720              }
 0721              thatSide.Type = bin.Type;
 722
 0723            } else {
 0724              break; // done simplifying
 725            }
 0726          }
 0727          break;
 728
 729        default:
 0730          break;
 731      }
 732      // our transformation above maintained the following invariant:
 0733      Contract.Assert(!FreeVariables(thatSide).Contains(bv));
 734
 735      // Now, see if the interesting side is simply bv itself
 0736      if (thisSide is IdentifierExpr && ((IdentifierExpr)thisSide).Var == bv) {
 737        // we're cool
 0738      } else {
 739        // no, the situation is more complicated than we care to understand
 0740        return -1;
 741      }
 742
 743      // Finally, check the bound variables of "thatSide". We allow "thatSide" to
 744      // depend on bound variables that are listed before "bv" (that is, a bound variable
 745      // "boundVars[k]" where "k < bvi"). By construction, "thatSide" does not depend
 746      // on "bv". Generally, for any bound variable "bj" that is listed after "bv"
 747      // (that is, "bj" is some "boundVars[j]" where "bvi < j"), we do not allow
 748      // "thatSide" to depend on "bv", but there is an important exception:
 749      // If
 750      //   *  "op" makes "thatSide" denote an integer upper bound on "bv" (or, analogously,
 751      //      a integer lower bound),
 752      //   *  "thatSide" depends on "bj",
 753      //   *  "thatSide" is monotonic in "bj",
 754      //   *  "bj" has a known integer upper bound "u",
 755      //   *  "u" does not depend on "bv" or any bound variable listed after "bv"
 756      //      (from the way we're constructing bounds, we already know that "u"
 757      //      does not depend on "bj" or any bound variable listed after "bj")
 758      // then we can substitute "u" for "bj" in "thatSide".
 759      // By going from right to left, we can make the rule above slightly more
 760      // liberal by considering a cascade of substitutions.
 0761      var fvThatSide = FreeVariables(thatSide);
 0762      for (int j = boundVars.Count; bvi + 1 <= --j;) {
 0763        if (fvThatSide.Contains(boundVars[j])) {
 0764          if (knownBounds[j] is ComprehensionExpr.IntBoundedPool) {
 0765            var jBounds = (ComprehensionExpr.IntBoundedPool)knownBounds[j];
 0766            Expression u = null;
 0767            if (op == BinaryExpr.ResolvedOpcode.Lt || op == BinaryExpr.ResolvedOpcode.Le) {
 0768              u = whereIsBv == 0 ? jBounds.UpperBound : jBounds.LowerBound;
 0769            } else if (op == BinaryExpr.ResolvedOpcode.Gt || op == BinaryExpr.ResolvedOpcode.Ge) {
 0770              u = whereIsBv == 0 ? jBounds.LowerBound : jBounds.UpperBound;
 0771            }
 0772            if (u != null && !FreeVariables(u).Contains(bv) && IsMonotonic(u, boundVars[j], true)) {
 0773              thatSide = Translator.Substitute(thatSide, boundVars[j], u);
 0774              fvThatSide = FreeVariables(thatSide);
 0775              continue;
 776            }
 0777          }
 0778          return -1; // forget about "bv OP thatSide"
 779        }
 0780      }
 781
 782      // As we return, also return the adjusted sides
 0783      if (whereIsBv == 0) {
 0784        e0 = thisSide;
 0785        e1 = thatSide;
 0786      } else {
 0787        e0 = thatSide;
 0788        e1 = thisSide;
 0789      }
 0790      return whereIsBv;
 0791    }
 792
 793    /// <summary>
 794    /// If "position", then returns "true" if "x" occurs only positively in "expr".
 795    /// If "!position", then returns "true" if "x" occurs only negatively in "expr".
 796    /// </summary>
 0797    public static bool IsMonotonic(Expression expr, IVariable x, bool position) {
 798      Contract.Requires(expr != null && expr.Type != null);
 799      Contract.Requires(x != null);
 800
 0801      if (expr is IdentifierExpr identifierExpr) {
 0802        return identifierExpr.Var != x || position;
 0803      } else if (expr is BinaryExpr binaryExpr) {
 0804        if (binaryExpr.ResolvedOp == BinaryExpr.ResolvedOpcode.Add) {
 0805          return IsMonotonic(binaryExpr.E0, x, position) && IsMonotonic(binaryExpr.E1, x, position);
 0806        } else if (binaryExpr.ResolvedOp == BinaryExpr.ResolvedOpcode.Sub) {
 0807          return IsMonotonic(binaryExpr.E0, x, position) && IsMonotonic(binaryExpr.E1, x, !position);
 808        }
 0809      }
 0810      return !FreeVariables(expr).Contains(x);
 0811    }
 812  }
 813}

/home/ubuntu/dafny-verifier/src/main/dafny_compiler/dafny/Source/DafnyCore/Resolver/NameResolutionAndTypeInference.cs

#LineLine coverage
 1#define TI_DEBUG_PRINT
 2//-----------------------------------------------------------------------------
 3//
 4// Copyright (C) Microsoft Corporation.  All Rights Reserved.
 5// Copyright by the contributors to the Dafny Project
 6// SPDX-License-Identifier: MIT
 7//
 8//-----------------------------------------------------------------------------
 9using System;
 10using System.Collections.Generic;
 11using System.Linq;
 12using System.Numerics;
 13using System.Diagnostics.Contracts;
 14using System.IO;
 15using System.Reflection;
 16using JetBrains.Annotations;
 17using Microsoft.BaseTypes;
 18using Microsoft.Boogie;
 19using Microsoft.CodeAnalysis.CSharp.Syntax;
 20using Microsoft.Dafny.Plugins;
 21using static Microsoft.Dafny.ErrorRegistry;
 22
 23namespace Microsoft.Dafny {
 24  public partial class Resolver {
 25    /// <summary>
 26    /// There are two rounds of name resolution + type inference. The "initialRound" parameter says which one to do.
 27    /// </summary>
 65228    void ResolveNamesAndInferTypes(List<TopLevelDecl> declarations, bool initialRound) {
 754229      foreach (TopLevelDecl topd in declarations) {
 186230        Contract.Assert(topd != null);
 186231        Contract.Assert(VisibleInScope(topd));
 186232        Contract.Assert(AllTypeConstraints.Count == 0);
 186233        Contract.Assert(currentClass == null);
 34
 186235        allTypeParameters.PushMarker();
 186236        ResolveTypeParameters(topd.TypeArgs, !initialRound, topd);
 37
 279338        if (initialRound) {
 93139          ResolveNamesAndInferTypesForOneDeclarationInitial(topd);
 186240        } else {
 93141          ResolveNamesAndInferTypesForOneDeclaration(topd);
 93142        }
 43
 186244        allTypeParameters.PopMarker();
 45
 186246        Contract.Assert(AllTypeConstraints.Count == 0);
 186247        Contract.Assert(currentClass == null);
 186248      }
 65249    }
 50
 51    /// <summary>
 52    /// Assumes type parameters of "topd" have already been pushed.
 53    /// </summary>
 93154    void ResolveNamesAndInferTypesForOneDeclarationInitial(TopLevelDecl topd) {
 93155      if (topd is NewtypeDecl newtypeDecl) {
 56        // this check can be done only after it has been determined that the redirected types do not involve cycles
 057        AddXConstraint(newtypeDecl.tok, "NumericType", newtypeDecl.BaseType, "newtypes must be based on some numeric typ
 58        // type check the constraint, if any
 059        if (newtypeDecl.Var != null) {
 060          Contract.Assert(object.ReferenceEquals(newtypeDecl.Var.Type, newtypeDecl.BaseType));  // follows from NewtypeD
 061          Contract.Assert(newtypeDecl.Constraint != null);  // follows from NewtypeDecl invariant
 62
 063          scope.PushMarker();
 064          scope.AllowInstance = false;
 065          var added = scope.Push(newtypeDecl.Var.Name, newtypeDecl.Var);
 066          Contract.Assert(added == Scope<IVariable>.PushResult.Success);
 067          ResolveExpression(newtypeDecl.Constraint, new ResolutionContext(new CodeContextWrapper(newtypeDecl, true), fal
 068          Contract.Assert(newtypeDecl.Constraint.Type != null);  // follows from postcondition of ResolveExpression
 069          ConstrainTypeExprBool(newtypeDecl.Constraint, "newtype constraint must be of type bool (instead got {0})");
 070          scope.PopMarker();
 071        }
 072        SolveAllTypeConstraints();
 73
 115574      } else if (topd is SubsetTypeDecl subsetTypeDecl) {
 75        // type check the constraint
 22476        Contract.Assert(object.ReferenceEquals(subsetTypeDecl.Var.Type, subsetTypeDecl.Rhs)); // follows from SubsetType
 22477        Contract.Assert(subsetTypeDecl.Constraint != null); // follows from SubsetTypeDecl invariant
 22478        scope.PushMarker();
 22479        scope.AllowInstance = false;
 22480        var added = scope.Push(subsetTypeDecl.Var.Name, subsetTypeDecl.Var);
 22481        Contract.Assert(added == Scope<IVariable>.PushResult.Success);
 22482        ResolveExpression(subsetTypeDecl.Constraint, new ResolutionContext(new CodeContextWrapper(subsetTypeDecl, true),
 22483        Contract.Assert(subsetTypeDecl.Constraint.Type != null); // follows from postcondition of ResolveExpression
 22484        ConstrainTypeExprBool(subsetTypeDecl.Constraint, "subset-type constraint must be of type bool (instead got {0})"
 22485        scope.PopMarker();
 22486        SolveAllTypeConstraints();
 22487      }
 88
 163889      if (topd is TopLevelDeclWithMembers cl) {
 70790        ResolveClassMemberBodiesInitial(cl);
 70791      }
 93192    }
 93
 93194    void ResolveNamesAndInferTypesForOneDeclaration(TopLevelDecl topd) {
 93195      if (topd is NewtypeDecl newtypeDecl) {
 096        if (newtypeDecl.Witness != null) {
 097          var codeContext = new CodeContextWrapper(newtypeDecl, newtypeDecl.WitnessKind == SubsetTypeDecl.WKind.Ghost);
 098          scope.PushMarker();
 099          scope.AllowInstance = false;
 0100          ResolveExpression(newtypeDecl.Witness, new ResolutionContext(codeContext, false));
 0101          scope.PopMarker();
 0102          ConstrainSubtypeRelation(newtypeDecl.Var.Type, newtypeDecl.Witness.Type, newtypeDecl.Witness, "witness express
 0103        }
 0104        SolveAllTypeConstraints();
 105
 1155106      } else if (topd is SubsetTypeDecl subsetTypeDecl) {
 224107        if (subsetTypeDecl.Witness != null) {
 0108          var codeContext = new CodeContextWrapper(subsetTypeDecl, subsetTypeDecl.WitnessKind == SubsetTypeDecl.WKind.Gh
 0109          scope.PushMarker();
 0110          scope.AllowInstance = false;
 0111          ResolveExpression(subsetTypeDecl.Witness, new ResolutionContext(codeContext, false));
 0112          scope.PopMarker();
 0113          ConstrainSubtypeRelation(subsetTypeDecl.Var.Type, subsetTypeDecl.Witness.Type, subsetTypeDecl.Witness,
 0114            "witness expression must have type '{0}' (got '{1}')", subsetTypeDecl.Var.Type, subsetTypeDecl.Witness.Type)
 0115        }
 224116        SolveAllTypeConstraints();
 117
 931118      } else if (topd is IteratorDecl iteratorDecl) {
 0119        ResolveIterator(iteratorDecl);
 120
 976121      } else if (topd is DatatypeDecl dt) {
 122        // resolve any default parameters
 2589123        foreach (var ctor in dt.Ctors) {
 594124          scope.PushMarker();
 594125          scope.AllowInstance = false;
 1184126          ctor.Formals.ForEach(p => scope.Push(p.Name, p));
 594127          ResolveAttributes(ctor, new ResolutionContext(new NoContext(topd.EnclosingModuleDefinition), false), true);
 594128          ResolveParameterDefaultValues(ctor.Formals, ResolutionContext.FromCodeContext(dt));
 594129          scope.PopMarker();
 594130        }
 269131      }
 132
 1638133      if (topd is TopLevelDeclWithMembers cl) {
 707134        ResolveClassMemberBodies(cl);
 707135      }
 136
 137      // resolve attributes
 931138      scope.PushMarker();
 931139      Contract.Assert(currentClass == null);
 931140      scope.AllowInstance = false;
 931141      if (topd is IteratorDecl iter) {
 0142        iter.Ins.ForEach(p => scope.Push(p.Name, p));
 0143      }
 931144      ResolveAttributes(topd, new ResolutionContext(new NoContext(topd.EnclosingModuleDefinition), false), true);
 931145      scope.PopMarker();
 931146    }
 147
 0148    void EagerAddAssignableConstraint(IToken tok, Type lhs, Type rhs, string errMsgFormat) {
 149      Contract.Requires(tok != null);
 150      Contract.Requires(lhs != null);
 151      Contract.Requires(rhs != null);
 152      Contract.Requires(errMsgFormat != null);
 0153      var lhsNormalized = lhs.Normalize();
 0154      var rhsNormalized = rhs.Normalize();
 0155      if (lhsNormalized is TypeProxy lhsProxy && !(rhsNormalized is TypeProxy)) {
 0156        Contract.Assert(lhsProxy.T == null); // otherwise, lhs.Normalize() above would have kept on going
 0157        AssignProxyAndHandleItsConstraints(lhsProxy, rhsNormalized, true);
 0158      } else {
 0159        AddAssignableConstraint(tok, lhs, rhs, errMsgFormat);
 0160      }
 0161    }
 112098162    public void AddAssignableConstraint(IToken tok, Type lhs, Type rhs, string errMsgFormat) {
 163      Contract.Requires(tok != null);
 164      Contract.Requires(lhs != null);
 165      Contract.Requires(rhs != null);
 166      Contract.Requires(errMsgFormat != null);
 112098167      AddXConstraint(tok, "Assignable", lhs, rhs, errMsgFormat);
 112098168    }
 42645169    private void AddXConstraint(IToken tok, string constraintName, Type type, string errMsgFormat) {
 170      Contract.Requires(tok != null);
 171      Contract.Requires(constraintName != null);
 172      Contract.Requires(type != null);
 173      Contract.Requires(errMsgFormat != null);
 42645174      var types = new Type[] { type };
 42645175      AllXConstraints.Add(new XConstraint(tok, constraintName, types, new TypeConstraint.ErrorMsgWithToken(tok, errMsgFo
 42645176    }
 8115177    void AddAssignableConstraint(IToken tok, Type lhs, Type rhs, TypeConstraint.ErrorMsg errMsg) {
 178      Contract.Requires(tok != null);
 179      Contract.Requires(lhs != null);
 180      Contract.Requires(rhs != null);
 181      Contract.Requires(errMsg != null);
 8115182      AddXConstraint(tok, "Assignable", lhs, rhs, errMsg);
 8115183    }
 3835184    private void AddXConstraint(IToken tok, string constraintName, Type type, TypeConstraint.ErrorMsg errMsg) {
 185      Contract.Requires(tok != null);
 186      Contract.Requires(constraintName != null);
 187      Contract.Requires(type != null);
 188      Contract.Requires(errMsg != null);
 3835189      var types = new Type[] { type };
 3835190      AllXConstraints.Add(new XConstraint(tok, constraintName, types, errMsg));
 3835191    }
 170681192    private void AddXConstraint(IToken tok, string constraintName, Type type0, Type type1, string errMsgFormat) {
 193      Contract.Requires(tok != null);
 194      Contract.Requires(constraintName != null);
 195      Contract.Requires(type0 != null);
 196      Contract.Requires(type1 != null);
 197      Contract.Requires(errMsgFormat != null);
 170681198      var types = new Type[] { type0, type1 };
 170681199      AllXConstraints.Add(new XConstraint(tok, constraintName, types, new TypeConstraint.ErrorMsgWithToken(tok, errMsgFo
 170681200    }
 25148201    private void AddXConstraint(IToken tok, string constraintName, Type type0, Type type1, TypeConstraint.ErrorMsg errMs
 202      Contract.Requires(tok != null);
 203      Contract.Requires(constraintName != null);
 204      Contract.Requires(type0 != null);
 205      Contract.Requires(type1 != null);
 206      Contract.Requires(errMsg != null);
 25148207      var types = new Type[] { type0, type1 };
 25148208      AllXConstraints.Add(new XConstraint(tok, constraintName, types, errMsg));
 25148209    }
 2089210    private void AddXConstraint(IToken tok, string constraintName, Type type, Expression expr0, Expression expr1, string
 211      Contract.Requires(tok != null);
 212      Contract.Requires(constraintName != null);
 213      Contract.Requires(type != null);
 214      Contract.Requires(expr0 != null);
 215      Contract.Requires(expr1 != null);
 216      Contract.Requires(errMsgFormat != null);
 2089217      var types = new Type[] { type };
 2089218      var exprs = new Expression[] { expr0, expr1 };
 2089219      AllXConstraints.Add(new XConstraintWithExprs(tok, constraintName, types, exprs, new TypeConstraint.ErrorMsgWithTok
 2089220    }
 221
 222    [System.Diagnostics.Conditional("TI_DEBUG_PRINT")]
 211604223    void PrintTypeConstraintState(int lbl) {
 423208224      if (!Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 211604225        return;
 226      }
 0227      Options.OutputWriter.WriteLine("DEBUG: ---------- type constraints ---------- {0} {1}", lbl, lbl == 0 && currentMe
 0228      foreach (var constraint in AllTypeConstraints) {
 0229        var super = constraint.Super.Normalize();
 0230        var sub = constraint.Sub.Normalize();
 0231        Options.OutputWriter.WriteLine("    {0} :> {1}", super is IntVarietiesSupertype ? "int-like" : super is RealVari
 0232      }
 0233      foreach (var xc in AllXConstraints) {
 0234        Options.OutputWriter.WriteLine("    {0}", xc);
 0235      }
 0236      Options.OutputWriter.WriteLine();
 0237      if (lbl % 2 == 1) {
 0238        Options.OutputWriter.WriteLine("DEBUG: --------------------------------------");
 0239      }
 211604240    }
 241
 242    /// <summary>
 243    /// Attempts to fully solve all type constraints.
 244    /// Upon failure, reports errors.
 245    /// Clears all constraints.
 246    /// </summary>
 11089247    public void SolveAllTypeConstraints() {
 11089248      PrintTypeConstraintState(0);
 11089249      PartiallySolveTypeConstraints(true);
 11089250      PrintTypeConstraintState(1);
 33267251      foreach (var constraint in AllTypeConstraints) {
 0252        if (Type.IsSupertype(constraint.Super, constraint.Sub)) {
 253          // unexpected condition -- PartiallySolveTypeConstraints is supposed to have continued until no more sub-typin
 0254          Contract.Assume(false, string.Format("DEBUG: Unexpectedly satisfied supertype relation ({0} :> {1}) |||| ", co
 0255        } else {
 0256          constraint.FlagAsError(this);
 0257        }
 0258      }
 33267259      foreach (var xc in AllXConstraints) {
 0260        if (xc.Confirm(this, true, out var convertedIntoOtherTypeConstraints, out var moreXConstraints)) {
 261          // unexpected condition -- PartiallySolveTypeConstraints is supposed to have continued until no more XConstrai
 0262          Contract.Assume(false, string.Format("DEBUG: Unexpectedly confirmed XConstraint: {0} |||| ", xc));
 0263        } else if (xc.CouldBeAnything()) {
 264          // suppress the error message; it will later be flagged as an underspecified type
 0265        } else {
 0266          xc.errorMsg.FlagAsError(this);
 0267        }
 0268      }
 11089269      TypeConstraint.ReportErrors(this, reporter);
 11089270      AllTypeConstraints.Clear();
 11089271      AllXConstraints.Clear();
 11089272    }
 273
 274    /// <summary>
 275    /// Adds type constraints for the expressions in the given attributes.
 276    ///
 277    /// If "solveConstraints" is "true", then the constraints are also solved. In this case, it is assumed on entry that
 278    /// prior type constraints. That is, the only type constraints being solved for are the ones in the given attributes
 279    /// </summary>
 302430280    public void ResolveAttributes(IAttributeBearingDeclaration attributeHost, ResolutionContext resolutionContext, bool 
 281      Contract.Requires(resolutionContext != null);
 282      Contract.Requires(attributeHost != null);
 283
 302430284      Contract.Assume(!solveConstraints || AllTypeConstraints.Count == 0);
 285
 286      // order does not matter much for resolution, so resolve them in reverse order
 910584287      foreach (var attr in attributeHost.Attributes.AsEnumerable()) {
 1098288        if (attr is UserSuppliedAttributes) {
 0289          var usa = (UserSuppliedAttributes)attr;
 0290          usa.Recognized = IsRecognizedAttribute(usa, attributeHost);
 0291        }
 2196292        if (attr.Args != null) {
 5916293          foreach (var arg in attr.Args) {
 874294            Contract.Assert(arg != null);
 874295            ResolveExpression(arg, resolutionContext);
 874296          }
 1098297        }
 1098298      }
 299
 306330300      if (solveConstraints) {
 3900301        SolveAllTypeConstraints();
 3900302      }
 302430303    }
 304
 305    /// <summary>
 306    /// "IsTwoState" implies that "old" and "fresh" expressions are allowed.
 307    /// </summary>
 759480308    public void ResolveExpression(Expression expr, ResolutionContext resolutionContext) {
 309
 310#if TEST_TYPE_SYNONYM_TRANSPARENCY
 311      ResolveExpressionX(expr, resolutionContext);
 312      // For testing purposes, change the type of "expr" to a type synonym (mwo-ha-ha-ha!)
 313      var t = expr.Type;
 314      Contract.Assert(t != null);
 315      var sd = new TypeSynonymDecl(expr.tok, "type#synonym#transparency#test", new TypeParameter.TypeParameterCharacteri
 316        new List<TypeParameter>(), resolutionContext.CodeContext.EnclosingModule, t, null);
 317      var ts = new UserDefinedType(expr.tok, "type#synonym#transparency#test", sd, new List<Type>(), null);
 318      expr.DebugTest_ChangeType(ts);
 319    }
 320    public void ResolveExpressionX(Expression expr, ResolutionContext resolutionContext) {
 321#endif
 322      Contract.Requires(expr != null);
 323      Contract.Requires(resolutionContext != null);
 324      Contract.Ensures(expr.Type != null);
 924307325      if (expr.Type != null) {
 326        // expression has already been resolved
 164827327        return;
 328      }
 594653329      DominatingStatementLabels.PushMarker();
 330
 331      // The following cases will resolve the subexpressions and will attempt to assign a type of expr.  However, if err
 332      // and it cannot be determined what the type of expr is, then it is fine to leave expr.Type as null.  In that case
 333      // of this method will assign proxy type to the expression, which reduces the number of error messages that are pr
 334      // while type checking the rest of the program.
 335
 655435336      if (expr is ParensExpression) {
 60782337        var e = (ParensExpression)expr;
 60782338        ResolveExpression(e.E, resolutionContext);
 60782339        var innerRange = e.E.RangeToken;
 60782340        e.ResolvedExpression = e.E; // Overwrites the range, which is not suitable for ParensExpressions
 60782341        e.E.RangeToken = innerRange;
 60782342        e.Type = e.E.Type;
 343
 596816344      } else if (expr is ChainingExpression) {
 2163345        var e = (ChainingExpression)expr;
 2163346        ResolveExpression(e.E, resolutionContext);
 2163347        e.ResolvedExpression = e.E;
 2163348        e.Type = e.E.Type;
 349
 549401350      } else if (expr is NegationExpression) {
 15530351        var e = (NegationExpression)expr;
 15530352        ResolveExpression(e.E, resolutionContext);
 15530353        e.Type = e.E.Type;
 15530354        AddXConstraint(e.E.tok, "NumericOrBitvector", e.E.Type, "type of unary - must be of a numeric or bitvector type 
 355        // Note, e.ResolvedExpression will be filled in during CheckTypeInference, at which time e.Type has been determi
 356
 772531357      } else if (expr is LiteralExpr) {
 240823358        LiteralExpr e = (LiteralExpr)expr;
 359
 240823360        if (e is StaticReceiverExpr) {
 0361          StaticReceiverExpr eStatic = (StaticReceiverExpr)e;
 0362          ResolveType(eStatic.tok, eStatic.UnresolvedType, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, nu
 0363          eStatic.Type = eStatic.UnresolvedType;
 240823364        } else {
 241047365          if (e.Value == null) {
 224366            e.Type = new InferredTypeProxy();
 224367            AddXConstraint(e.tok, "IsNullableRefType", e.Type, "type of 'null' is a reference type, but it is used as {0
 310535368          } else if (e.Value is BigInteger) {
 69712369            var proxy = new InferredTypeProxy();
 69712370            e.Type = proxy;
 69712371            ConstrainSubtypeRelation(new IntVarietiesSupertype(), e.Type, e.tok, "integer literal used as if it had type
 262474372          } else if (e.Value is BaseTypes.BigDec) {
 21875373            var proxy = new InferredTypeProxy();
 21875374            e.Type = proxy;
 21875375            ConstrainSubtypeRelation(new RealVarietiesSupertype(), e.Type, e.tok, "type of real literal is used as {0}",
 199790376          } else if (e.Value is bool) {
 28903377            e.Type = Type.Bool;
 202372378          } else if (e is CharLiteralExpr) {
 53360379            e.Type = Type.Char;
 186858380          } else if (e is StringLiteralExpr) {
 66749381            e.Type = Type.String();
 66749382            ResolveType(e.tok, e.Type, resolutionContext, ResolveTypeOptionEnum.DontInfer, null);
 66749383          } else {
 0384            Contract.Assert(false); throw new cce.UnreachableException();  // unexpected literal type
 385          }
 240823386        }
 516178387      } else if (expr is ThisExpr) {
 0388        if (!scope.AllowInstance) {
 0389          reporter.Error(MessageSource.Resolver, expr, "'this' is not allowed in a 'static' context");
 0390        }
 0391        if (currentClass is ClassDecl cd && cd.IsDefaultClass) {
 392          // there's no type
 0393        } else {
 0394          if (currentClass == null) {
 0395            Contract.Assert(reporter.HasErrors);
 0396          } else {
 0397            expr.Type = GetThisType(expr.tok, currentClass);  // do this regardless of scope.AllowInstance, for better e
 0398          }
 0399        }
 400
 275355401      } else if (expr is IdentifierExpr) {
 0402        var e = (IdentifierExpr)expr;
 0403        e.Var = scope.Find(e.Name);
 0404        if (e.Var != null) {
 0405          expr.Type = e.Var.Type;
 0406        } else {
 0407          reporter.Error(MessageSource.Resolver, expr, "Identifier does not denote a local variable, parameter, or bound
 0408        }
 409
 281815410      } else if (expr is DatatypeValue) {
 6460411        DatatypeValue dtv = (DatatypeValue)expr;
 6460412        if (!moduleInfo.TopLevels.TryGetValue(dtv.DatatypeName, out var d)) {
 0413          reporter.Error(MessageSource.Resolver, expr.tok, "Undeclared datatype: {0}", dtv.DatatypeName);
 6460414        } else if (d is AmbiguousTopLevelDecl) {
 0415          var ad = (AmbiguousTopLevelDecl)d;
 0416          reporter.Error(MessageSource.Resolver, expr.tok, "The name {0} ambiguously refers to a type in one of the modu
 6460417        } else if (!(d is DatatypeDecl)) {
 0418          reporter.Error(MessageSource.Resolver, expr.tok, "Expected datatype: {0}", dtv.DatatypeName);
 6460419        } else {
 6460420          ResolveDatatypeValue(resolutionContext, dtv, (DatatypeDecl)d, null);
 6460421        }
 422
 291547423      } else if (expr is DisplayExpression) {
 16192424        DisplayExpression e = (DisplayExpression)expr;
 16192425        Type elementType = new InferredTypeProxy() { KeepConstraints = true };
 148554426        foreach (Expression ee in e.Elements) {
 33326427          ResolveExpression(ee, resolutionContext);
 33326428          Contract.Assert(ee.Type != null);  // follows from postcondition of ResolveExpression
 33326429          ConstrainSubtypeRelation(elementType, ee.Type, ee.tok, "All elements of display must have some common supertyp
 33326430        }
 20901431        if (expr is SetDisplayExpr) {
 4709432          var se = (SetDisplayExpr)expr;
 4709433          expr.Type = new SetType(se.Finite, elementType);
 18747434        } else if (expr is MultiSetDisplayExpr) {
 2555435          expr.Type = new MultiSetType(elementType);
 11483436        } else {
 8928437          expr.Type = new SeqType(elementType);
 8928438        }
 279302439      } else if (expr is MapDisplayExpr) {
 10407440        MapDisplayExpr e = (MapDisplayExpr)expr;
 10407441        Type domainType = new InferredTypeProxy();
 10407442        Type rangeType = new InferredTypeProxy();
 123708443        foreach (ExpressionPair p in e.Elements) {
 30829444          ResolveExpression(p.A, resolutionContext);
 30829445          Contract.Assert(p.A.Type != null);  // follows from postcondition of ResolveExpression
 30829446          ConstrainSubtypeRelation(domainType, p.A.Type, p.A.tok, "All elements of display must have some common superty
 30829447          ResolveExpression(p.B, resolutionContext);
 30829448          Contract.Assert(p.B.Type != null);  // follows from postcondition of ResolveExpression
 30829449          ConstrainSubtypeRelation(rangeType, p.B.Type, p.B.tok, "All elements of display must have some common supertyp
 30829450        }
 10407451        expr.Type = new MapType(e.Finite, domainType, rangeType);
 379255452      } else if (expr is NameSegment) {
 126552453        var e = (NameSegment)expr;
 126552454        ResolveNameSegment(e, true, null, resolutionContext, false);
 455
 126552456        if (e.Type is Resolver_IdentifierExpr.ResolverType_Module) {
 0457          reporter.Error(MessageSource.Resolver, e.tok, "name of module ({0}) is used as a variable", e.Name);
 0458          e.ResetTypeAssignment();  // the rest of type checking assumes actual types
 126552459        } else if (e.Type is Resolver_IdentifierExpr.ResolverType_Type) {
 0460          reporter.Error(MessageSource.Resolver, e.tok, "name of type ({0}) is used as a variable", e.Name);
 0461          e.ResetTypeAssignment();  // the rest of type checking assumes actual types
 0462        }
 463
 250130464      } else if (expr is ExprDotName) {
 7834465        var e = (ExprDotName)expr;
 7834466        ResolveDotSuffix(e, true, null, resolutionContext, false);
 7834467        if (e.Type is Resolver_IdentifierExpr.ResolverType_Module) {
 0468          reporter.Error(MessageSource.Resolver, e.tok, "name of module ({0}) is used as a variable", e.SuffixName);
 0469          e.ResetTypeAssignment();  // the rest of type checking assumes actual types
 7834470        } else if (e.Type is Resolver_IdentifierExpr.ResolverType_Type) {
 0471          reporter.Error(MessageSource.Resolver, e.tok, "name of type ({0}) is used as a variable", e.SuffixName);
 0472          e.ResetTypeAssignment();  // the rest of type checking assumes actual types
 0473        }
 474
 115744475      } else if (expr is ApplySuffix) {
 0476        var e = (ApplySuffix)expr;
 0477        ResolveApplySuffix(e, resolutionContext, false);
 478
 107910479      } else if (expr is MemberSelectExpr) {
 0480        var e = (MemberSelectExpr)expr;
 0481        ResolveExpression(e.Obj, resolutionContext);
 0482        Contract.Assert(e.Obj.Type != null);  // follows from postcondition of ResolveExpression
 0483        var member = ResolveMember(expr.tok, e.Obj.Type, e.MemberName, out var tentativeReceiverType);
 0484        if (member == null) {
 485          // error has already been reported by ResolveMember
 0486        } else if (member is Function) {
 0487          var fn = member as Function;
 0488          e.Member = fn;
 0489          if (fn is TwoStateFunction && !resolutionContext.IsTwoState) {
 0490            reporter.Error(MessageSource.Resolver, e.tok, "a two-state function can be used only in a two-state context"
 0491          }
 492          // build the type substitution map
 0493          e.TypeApplication_AtEnclosingClass = tentativeReceiverType.TypeArgs;
 0494          e.TypeApplication_JustMember = new List<Type>();
 495          Dictionary<TypeParameter, Type> subst;
 0496          var ctype = tentativeReceiverType as UserDefinedType;
 0497          if (ctype == null) {
 0498            subst = new Dictionary<TypeParameter, Type>();
 0499          } else {
 0500            subst = TypeParameter.SubstitutionMap(ctype.ResolvedClass.TypeArgs, ctype.TypeArgs);
 0501          }
 0502          foreach (var tp in fn.TypeArgs) {
 0503            Type prox = new InferredTypeProxy();
 0504            subst[tp] = prox;
 0505            e.TypeApplication_JustMember.Add(prox);
 0506          }
 0507          subst = BuildTypeArgumentSubstitute(subst);
 0508          e.Type = SelectAppropriateArrowTypeForFunction(fn, subst, builtIns);
 0509        } else if (member is Field) {
 0510          var field = (Field)member;
 0511          e.Member = field;
 0512          e.TypeApplication_AtEnclosingClass = tentativeReceiverType.TypeArgs;
 0513          e.TypeApplication_JustMember = new List<Type>();
 0514          if (e.Obj is StaticReceiverExpr && !field.IsStatic) {
 0515            reporter.Error(MessageSource.Resolver, expr, "a field must be selected via an object, not just a class name"
 0516          }
 0517          var ctype = tentativeReceiverType as UserDefinedType;
 0518          if (ctype == null) {
 0519            e.Type = field.Type;
 0520          } else {
 0521            Contract.Assert(ctype.ResolvedClass != null); // follows from postcondition of ResolveMember
 522            // build the type substitution map
 0523            var subst = TypeParameter.SubstitutionMap(ctype.ResolvedClass.TypeArgs, ctype.TypeArgs);
 0524            e.Type = field.Type.Subst(subst);
 0525          }
 0526        } else {
 0527          reporter.Error(MessageSource.Resolver, expr, "member {0} in type {1} does not refer to a field or a function",
 0528        }
 529
 121411530      } else if (expr is SeqSelectExpr) {
 13501531        SeqSelectExpr e = (SeqSelectExpr)expr;
 13501532        ResolveSeqSelectExpr(e, resolutionContext);
 533
 107910534      } else if (expr is MultiSelectExpr) {
 0535        MultiSelectExpr e = (MultiSelectExpr)expr;
 536
 0537        ResolveExpression(e.Array, resolutionContext);
 0538        Contract.Assert(e.Array.Type != null);  // follows from postcondition of ResolveExpression
 0539        Contract.Assert(e.Array.Type.TypeArgs != null);  // if it is null, should make a 1-element list with a Proxy
 0540        Type elementType = e.Array.Type.TypeArgs.Count > 0 ?
 0541          e.Array.Type.TypeArgs[0] :
 0542          new InferredTypeProxy();
 0543        ConstrainSubtypeRelation(ResolvedArrayType(e.Array.tok, e.Indices.Count, elementType, resolutionContext, true), 
 0544          "array selection requires an array{0} (got {1})", e.Indices.Count, e.Array.Type);
 0545        int i = 0;
 0546        foreach (Expression idx in e.Indices) {
 0547          Contract.Assert(idx != null);
 0548          ResolveExpression(idx, resolutionContext);
 0549          Contract.Assert(idx.Type != null);  // follows from postcondition of ResolveExpression
 0550          ConstrainToIntegerType(idx, true, "array selection requires integer- or bitvector-based numeric indices (got {
 0551          i++;
 0552        }
 0553        e.Type = elementType;
 554
 96498555      } else if (expr is SeqUpdateExpr) {
 2089556        SeqUpdateExpr e = (SeqUpdateExpr)expr;
 2089557        ResolveExpression(e.Seq, resolutionContext);
 2089558        Contract.Assert(e.Seq.Type != null);  // follows from postcondition of ResolveExpression
 2089559        ResolveExpression(e.Index, resolutionContext);
 2089560        ResolveExpression(e.Value, resolutionContext);
 2089561        AddXConstraint(expr.tok, "SeqUpdatable", e.Seq.Type, e.Index, e.Value, "update requires a sequence, map, or mult
 2089562        expr.Type = new InferredTypeProxy(); // drop type constraints
 2089563        ConstrainSubtypeRelation(
 2089564          super: expr.Type, sub: e.Seq.Type, // expr.Type generalizes e.Seq.Type by dropping constraints
 2089565          exprForToken: expr,
 2089566          msg: "Update expression used with type '{0}'", e.Seq.Type);
 94409567      } else if (expr is DatatypeUpdateExpr) {
 0568        var e = (DatatypeUpdateExpr)expr;
 0569        ResolveExpression(e.Root, resolutionContext);
 0570        var ty = PartiallyResolveTypeForMemberSelection(expr.tok, e.Root.Type);
 0571        if (!ty.IsDatatype) {
 0572          reporter.Error(MessageSource.Resolver, expr, "datatype update expression requires a root expression of a datat
 0573        } else {
 0574          var (ghostLet, compiledLet) = ResolveDatatypeUpdate(expr.tok, e.Root, ty.AsDatatype, e.Updates, resolutionCont
 0575            out var members, out var legalSourceConstructors);
 0576          Contract.Assert((ghostLet == null) == (compiledLet == null));
 0577          if (ghostLet != null) {
 0578            e.ResolvedExpression = ghostLet; // this might be replaced by e.ResolvedCompiledExpression in CheckIsCompila
 0579            e.ResolvedCompiledExpression = compiledLet;
 0580            e.Members = members;
 0581            e.LegalSourceConstructors = legalSourceConstructors;
 0582            expr.Type = ghostLet.Type;
 0583          }
 0584        }
 585
 92320586      } else if (expr is FunctionCallExpr) {
 0587        var e = (FunctionCallExpr)expr;
 0588        ResolveFunctionCallExpr(e, resolutionContext);
 589
 92320590      } else if (expr is ApplyExpr) {
 0591        var e = (ApplyExpr)expr;
 0592        ResolveExpression(e.Function, resolutionContext);
 0593        foreach (var arg in e.Args) {
 0594          ResolveExpression(arg, resolutionContext);
 0595        }
 596
 597        // TODO: the following should be replaced by a type-class constraint that constrains the types of e.Function, e.
 0598        var fnType = e.Function.Type.AsArrowType;
 0599        if (fnType == null) {
 0600          reporter.Error(MessageSource.Resolver, e.tok,
 0601            "non-function expression (of type {0}) is called with parameters", e.Function.Type);
 0602        } else if (fnType.Arity != e.Args.Count) {
 0603          reporter.Error(MessageSource.Resolver, e.tok,
 0604            "wrong number of arguments to function application (function type '{0}' expects {1}, got {2})", fnType,
 0605            fnType.Arity, e.Args.Count);
 0606        } else {
 0607          for (var i = 0; i < fnType.Arity; i++) {
 0608            AddAssignableConstraint(e.Args[i].tok, fnType.Args[i], e.Args[i].Type,
 0609              "type mismatch for argument" + (fnType.Arity == 1 ? "" : " " + i) + " (function expects {0}, got {1})");
 0610          }
 0611        }
 612
 0613        expr.Type = fnType == null ? new InferredTypeProxy() : fnType.Result;
 614
 92320615      } else if (expr is SeqConstructionExpr) {
 0616        var e = (SeqConstructionExpr)expr;
 0617        var elementType = e.ExplicitElementType ?? new InferredTypeProxy();
 0618        ResolveType(e.tok, elementType, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 0619        ResolveExpression(e.N, resolutionContext);
 0620        ConstrainToIntegerType(e.N, false, "sequence construction must use an integer-based expression for the sequence 
 0621        ResolveExpression(e.Initializer, resolutionContext);
 0622        var arrowType = new ArrowType(e.tok, builtIns.ArrowTypeDecls[1], new List<Type>() { builtIns.Nat() }, elementTyp
 0623        var hintString = " (perhaps write '_ =>' in front of the expression you gave in order to make it an arrow type)"
 0624        ConstrainSubtypeRelation(arrowType, e.Initializer.Type, e.Initializer, "sequence-construction initializer expres
 0625          arrowType, e.Initializer.Type, new LazyString_OnTypeEquals(elementType, e.Initializer.Type, hintString));
 0626        expr.Type = new SeqType(elementType);
 627
 93030628      } else if (expr is MultiSetFormingExpr) {
 710629        MultiSetFormingExpr e = (MultiSetFormingExpr)expr;
 710630        ResolveExpression(e.E, resolutionContext);
 710631        var elementType = new InferredTypeProxy();
 710632        AddXConstraint(e.E.tok, "MultiSetConvertible", e.E.Type, elementType, "can only form a multiset from a seq or se
 710633        expr.Type = new MultiSetType(elementType);
 634
 92320635      } else if (expr is OldExpr) {
 0636        var e = (OldExpr)expr;
 0637        e.AtLabel = ResolveDominatingLabelInExpr(expr.tok, e.At, "old", resolutionContext);
 0638        ResolveExpression(e.E, new ResolutionContext(resolutionContext.CodeContext, false) with { InOld = true });
 0639        expr.Type = e.E.Type;
 640
 91610641      } else if (expr is UnchangedExpr) {
 0642        var e = (UnchangedExpr)expr;
 0643        e.AtLabel = ResolveDominatingLabelInExpr(expr.tok, e.At, "unchanged", resolutionContext);
 0644        foreach (var fe in e.Frame) {
 0645          ResolveFrameExpression(fe, FrameExpressionUse.Unchanged, resolutionContext);
 0646        }
 0647        expr.Type = Type.Bool;
 648
 91610649      } else if (expr is FreshExpr) {
 0650        var e = (FreshExpr)expr;
 0651        ResolveExpression(e.E, resolutionContext);
 0652        e.AtLabel = ResolveDominatingLabelInExpr(expr.tok, e.At, "fresh", resolutionContext);
 653        // the type of e.E must be either an object or a set/seq of objects
 0654        AddXConstraint(expr.tok, "Freshable", e.E.Type, "the argument of a fresh expression must denote an object or a s
 0655        expr.Type = Type.Bool;
 656
 100855657      } else if (expr is UnaryOpExpr) {
 9245658        var e = (UnaryOpExpr)expr;
 9245659        ResolveExpression(e.E, resolutionContext);
 9245660        Contract.Assert(e.E.Type != null);  // follows from postcondition of ResolveExpression
 9245661        switch (e.Op) {
 662          case UnaryOpExpr.Opcode.Not:
 25663            AddXConstraint(e.E.tok, "BooleanBits", e.E.Type, "logical/bitwise negation expects a boolean or bitvector ar
 25664            expr.Type = e.E.Type;
 25665            break;
 666          case UnaryOpExpr.Opcode.Cardinality:
 9220667            AddXConstraint(expr.tok, "Sizeable", e.E.Type, "size operator expects a collection argument (instead got {0}
 9220668            expr.Type = Type.Int;
 9220669            break;
 670          case UnaryOpExpr.Opcode.Allocated:
 671            // the argument is allowed to have any type at all
 0672            expr.Type = Type.Bool;
 0673            if (2 <= Options.Allocated &&
 0674              ((resolutionContext.CodeContext is Function && !resolutionContext.InOld) || resolutionContext.CodeContext 
 0675              var declKind = CodeContextWrapper.Unwrap(resolutionContext.CodeContext) is RedirectingTypeDecl redir ? red
 0676              reporter.Error(MessageSource.Resolver, expr, "a {0} definition is not allowed to depend on the set of allo
 0677            }
 0678            break;
 679          default:
 0680            Contract.Assert(false); throw new cce.UnreachableException();  // unexpected unary operator
 681        }
 682
 683        // We do not have enough information to compute `e.ResolvedOp` yet.
 684        // For binary operators the computation happens in `CheckTypeInference`.
 685        // For unary operators it happens lazily in the getter of `e.ResolvedOp`.
 91610686      } else if (expr is ConversionExpr) {
 0687        var e = (ConversionExpr)expr;
 0688        ResolveExpression(e.E, resolutionContext);
 0689        var prevErrorCount = reporter.Count(ErrorLevel.Error);
 0690        ResolveType(e.tok, e.ToType, resolutionContext, new ResolveTypeOption(ResolveTypeOptionEnum.InferTypeProxies), n
 0691        if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 0692          if (e.ToType.IsNumericBased(Type.NumericPersuasion.Int)) {
 0693            AddXConstraint(expr.tok, "NumericOrBitvectorOrCharOrORDINAL", e.E.Type, "type conversion to an int-based typ
 0694          } else if (e.ToType.IsNumericBased(Type.NumericPersuasion.Real)) {
 0695            AddXConstraint(expr.tok, "NumericOrBitvectorOrCharOrORDINAL", e.E.Type, "type conversion to a real-based typ
 0696          } else if (e.ToType.IsBitVectorType) {
 0697            AddXConstraint(expr.tok, "NumericOrBitvectorOrCharOrORDINAL", e.E.Type, "type conversion to a bitvector-base
 0698          } else if (e.ToType.IsCharType) {
 0699            AddXConstraint(expr.tok, "NumericOrBitvectorOrCharOrORDINAL", e.E.Type, "type conversion to a char type is a
 0700          } else if (e.ToType.IsBigOrdinalType) {
 0701            AddXConstraint(expr.tok, "NumericOrBitvectorOrCharOrORDINAL", e.E.Type, "type conversion to an ORDINAL type 
 0702          } else if (e.ToType.IsRefType) {
 0703            AddAssignableConstraint(expr.tok, e.ToType, e.E.Type, "type cast to reference type '{0}' must be from an exp
 0704          } else {
 0705            reporter.Error(MessageSource.Resolver, expr, "type conversions are not supported to this type (got {0})", e.
 0706          }
 0707          e.Type = e.ToType;
 0708        } else {
 0709          e.Type = new InferredTypeProxy();
 0710        }
 711
 82365712      } else if (expr is TypeTestExpr) {
 0713        var e = (TypeTestExpr)expr;
 0714        ResolveExpression(e.E, resolutionContext);
 0715        var prevErrorCount = reporter.Count(ErrorLevel.Error);
 0716        ResolveType(e.tok, e.ToType, resolutionContext, new ResolveTypeOption(ResolveTypeOptionEnum.InferTypeProxies), n
 0717        AddAssignableConstraint(expr.tok, e.ToType, e.E.Type, "type test for type '{0}' must be from an expression assig
 0718        e.Type = Type.Bool;
 719
 146853720      } else if (expr is BinaryExpr) {
 721
 64488722        BinaryExpr e = (BinaryExpr)expr;
 64488723        ResolveExpression(e.E0, resolutionContext);
 64488724        Contract.Assert(e.E0.Type != null);  // follows from postcondition of ResolveExpression
 64488725        ResolveExpression(e.E1, resolutionContext);
 64488726        Contract.Assert(e.E1.Type != null);  // follows from postcondition of ResolveExpression
 727
 64488728        switch (e.Op) {
 729          case BinaryExpr.Opcode.Iff:
 730          case BinaryExpr.Opcode.Imp:
 731          case BinaryExpr.Opcode.Exp:
 732          case BinaryExpr.Opcode.And:
 17441733          case BinaryExpr.Opcode.Or: {
 17441734              ConstrainSubtypeRelation(Type.Bool, e.E0.Type, expr, "first argument to {0} must be of type bool (instead 
 17441735              var secondArgumentDescription = e.E1.tok is QuantifiedVariableRangeToken
 17441736                ? "range of quantified variable" : "second argument to {0}";
 17441737              ConstrainSubtypeRelation(Type.Bool, e.E1.Type, expr, secondArgumentDescription + " must be of type bool (i
 17441738              expr.Type = Type.Bool;
 17441739              break;
 740            }
 741
 742          case BinaryExpr.Opcode.Eq:
 743          case BinaryExpr.Opcode.Neq:
 22781744            AddXConstraint(expr.tok, "Equatable", e.E0.Type, e.E1.Type, "arguments must have comparable types (got {0} a
 22781745            expr.Type = Type.Bool;
 22781746            break;
 747
 748          case BinaryExpr.Opcode.Disjoint:
 40749            Type disjointArgumentsType = new InferredTypeProxy();
 40750            ConstrainSubtypeRelation(disjointArgumentsType, e.E0.Type, expr, "arguments to {2} must have a common supert
 40751            ConstrainSubtypeRelation(disjointArgumentsType, e.E1.Type, expr, "arguments to {2} must have a common supert
 40752            AddXConstraint(expr.tok, "Disjointable", disjointArgumentsType, "arguments must be of a set or multiset type
 40753            expr.Type = Type.Bool;
 40754            break;
 755
 756          case BinaryExpr.Opcode.Lt:
 7137757          case BinaryExpr.Opcode.Le: {
 7137758              if (e.Op == BinaryExpr.Opcode.Lt && (PartiallyResolveTypeForMemberSelection(e.E0.tok, e.E0.Type).IsIndData
 0759                AddXConstraint(expr.tok, "RankOrderable", e.E0.Type, e.E1.Type, "arguments to rank comparison must be da
 0760                e.ResolvedOp = BinaryExpr.ResolvedOpcode.RankLt;
 7137761              } else {
 7137762                var cmpType = new InferredTypeProxy();
 7137763                var err = new TypeConstraint.ErrorMsgWithToken(expr.tok, "arguments to {2} must have a common supertype 
 7137764                ConstrainSubtypeRelation(cmpType, e.E0.Type, err);
 7137765                ConstrainSubtypeRelation(cmpType, e.E1.Type, err);
 7137766                AddXConstraint(expr.tok, "Orderable_Lt", e.E0.Type, e.E1.Type,
 7137767                  "arguments to " + BinaryExpr.OpcodeString(e.Op) + " must be of a numeric type, bitvector type, ORDINAL
 7137768              }
 7137769              expr.Type = Type.Bool;
 7137770            }
 7137771            break;
 772
 773          case BinaryExpr.Opcode.Gt:
 8717774          case BinaryExpr.Opcode.Ge: {
 8717775              if (e.Op == BinaryExpr.Opcode.Gt && (PartiallyResolveTypeForMemberSelection(e.E0.tok, e.E0.Type).IsIndData
 0776                AddXConstraint(expr.tok, "RankOrderable", e.E1.Type, e.E0.Type, "arguments to rank comparison must be da
 0777                e.ResolvedOp = BinaryExpr.ResolvedOpcode.RankGt;
 8717778              } else {
 8717779                var cmpType = new InferredTypeProxy();
 8717780                var err = new TypeConstraint.ErrorMsgWithToken(expr.tok, "arguments to {2} must have a common supertype 
 8717781                ConstrainSubtypeRelation(cmpType, e.E0.Type, err);
 8717782                ConstrainSubtypeRelation(cmpType, e.E1.Type, err);
 8717783                AddXConstraint(expr.tok, "Orderable_Gt", e.E0.Type, e.E1.Type,
 8717784                  "arguments to " + BinaryExpr.OpcodeString(e.Op) + " must be of a numeric type, bitvector type, ORDINAL
 8717785              }
 8717786              expr.Type = Type.Bool;
 8717787            }
 8717788            break;
 789
 790          case BinaryExpr.Opcode.LeftShift:
 0791          case BinaryExpr.Opcode.RightShift: {
 0792              expr.Type = new InferredTypeProxy();
 0793              AddXConstraint(e.tok, "IsBitvector", expr.Type, "type of " + BinaryExpr.OpcodeString(e.Op) + " must be a b
 0794              ConstrainSubtypeRelation(expr.Type, e.E0.Type, expr.tok, "type of left argument to " + BinaryExpr.OpcodeSt
 0795              AddXConstraint(expr.tok, "IntLikeOrBitvector", e.E1.Type, "type of right argument to " + BinaryExpr.Opcode
 0796            }
 0797            break;
 798
 1330799          case BinaryExpr.Opcode.Add: {
 1330800              expr.Type = new InferredTypeProxy();
 1330801              AddXConstraint(e.tok, "Plussable", expr.Type, "type of + must be of a numeric type, a bitvector type, ORDI
 1330802              ConstrainSubtypeRelation(expr.Type, e.E0.Type, expr.tok, "type of left argument to + ({0}) must agree with
 1330803              ConstrainSubtypeRelation(expr.Type, e.E1.Type, expr.tok, "type of right argument to + ({0}) must agree wit
 1330804            }
 1330805            break;
 806
 1299807          case BinaryExpr.Opcode.Sub: {
 1299808              expr.Type = new InferredTypeProxy();
 1299809              AddXConstraint(e.tok, "Minusable", expr.Type, "type of - must be of a numeric type, bitvector type, ORDINA
 1299810              ConstrainSubtypeRelation(expr.Type, e.E0.Type, expr.tok, "type of left argument to - ({0}) must agree with
 811              // The following handles map subtraction, but does not in an unfortunately restrictive way.
 812              // First, it would be nice to delay the decision of it this is a map subtraction or not. This settles
 813              // for the simple way to decide based on what is currently known about the result type, which is also
 814              // done, for example, when deciding if "<" denotes rank ordering on datatypes.
 815              // Second, for map subtraction, it would be nice to allow the right-hand operand to be either a set or
 816              // an iset. That would also lead to further complexity in the code, so this code restricts the right-hand
 817              // operand to be a set.
 1299818              var eType = PartiallyResolveTypeForMemberSelection(expr.tok, expr.Type).AsMapType;
 1583819              if (eType != null) {
 820                // allow "map - set == map"
 284821                var expected = new SetType(true, eType.Domain);
 284822                ConstrainSubtypeRelation(expected, e.E1.Type, expr.tok, "map subtraction expects right-hand operand to h
 1299823              } else {
 1015824                ConstrainSubtypeRelation(expr.Type, e.E1.Type, expr.tok, "type of right argument to - ({0}) must agree w
 1015825              }
 1299826            }
 1299827            break;
 828
 195829          case BinaryExpr.Opcode.Mul: {
 195830              expr.Type = new InferredTypeProxy();
 195831              AddXConstraint(e.tok, "Mullable", expr.Type, "type of * must be of a numeric type, bitvector type, or a se
 195832              ConstrainSubtypeRelation(expr.Type, e.E0.Type, expr.tok, "type of left argument to * ({0}) must agree with
 195833              ConstrainSubtypeRelation(expr.Type, e.E1.Type, expr.tok, "type of right argument to * ({0}) must agree wit
 195834            }
 195835            break;
 836
 837          case BinaryExpr.Opcode.In:
 838          case BinaryExpr.Opcode.NotIn:
 4267839            var subjectDescription = e.E1.tok is QuantifiedVariableDomainToken
 4267840              ? "domain of quantified variable" : "second argument to \"" + BinaryExpr.OpcodeString(e.Op) + "\"";
 4267841            AddXConstraint(expr.tok, "Innable", e.E1.Type, e.E0.Type, subjectDescription + " must be a set, multiset, or
 4267842            expr.Type = Type.Bool;
 4267843            break;
 844
 845          case BinaryExpr.Opcode.Div:
 668846            expr.Type = new InferredTypeProxy();
 668847            AddXConstraint(expr.tok, "NumericOrBitvector", expr.Type, "arguments to " + BinaryExpr.OpcodeString(e.Op) + 
 668848            ConstrainSubtypeRelation(expr.Type, e.E0.Type,
 668849              expr, "type of left argument to " + BinaryExpr.OpcodeString(e.Op) + " ({0}) must agree with the result typ
 668850              e.E0.Type, expr.Type);
 668851            ConstrainSubtypeRelation(expr.Type, e.E1.Type,
 668852              expr, "type of right argument to " + BinaryExpr.OpcodeString(e.Op) + " ({0}) must agree with the result ty
 668853              e.E1.Type, expr.Type);
 668854            break;
 855
 856          case BinaryExpr.Opcode.Mod:
 613857            expr.Type = new InferredTypeProxy();
 613858            AddXConstraint(expr.tok, "IntLikeOrBitvector", expr.Type, "arguments to " + BinaryExpr.OpcodeString(e.Op) + 
 613859            ConstrainSubtypeRelation(expr.Type, e.E0.Type,
 613860              expr, "type of left argument to " + BinaryExpr.OpcodeString(e.Op) + " ({0}) must agree with the result typ
 613861              e.E0.Type, expr.Type);
 613862            ConstrainSubtypeRelation(expr.Type, e.E1.Type,
 613863              expr, "type of right argument to " + BinaryExpr.OpcodeString(e.Op) + " ({0}) must agree with the result ty
 613864              e.E1.Type, expr.Type);
 613865            break;
 866
 867          case BinaryExpr.Opcode.BitwiseAnd:
 868          case BinaryExpr.Opcode.BitwiseOr:
 869          case BinaryExpr.Opcode.BitwiseXor:
 0870            expr.Type = NewIntegerBasedProxy(expr.tok);
 0871            var errFormat = "first argument to " + BinaryExpr.OpcodeString(e.Op) + " must be of a bitvector type (instea
 0872            ConstrainSubtypeRelation(expr.Type, e.E0.Type, expr, errFormat, e.E0.Type);
 0873            AddXConstraint(expr.tok, "IsBitvector", e.E0.Type, errFormat);
 0874            errFormat = "second argument to " + BinaryExpr.OpcodeString(e.Op) + " must be of a bitvector type (instead g
 0875            ConstrainSubtypeRelation(expr.Type, e.E1.Type, expr, errFormat, e.E1.Type);
 0876            AddXConstraint(expr.tok, "IsBitvector", e.E1.Type, errFormat);
 0877            break;
 878
 879          default:
 0880            Contract.Assert(false); throw new cce.UnreachableException();  // unexpected operator
 881        }
 882        // We should also fill in e.ResolvedOp, but we may not have enough information for that yet.  So, instead, delay
 883        // setting e.ResolvedOp until inside CheckTypeInference.
 884
 82365885      } else if (expr is TernaryExpr) {
 0886        var e = (TernaryExpr)expr;
 0887        ResolveExpression(e.E0, resolutionContext);
 0888        ResolveExpression(e.E1, resolutionContext);
 0889        ResolveExpression(e.E2, resolutionContext);
 0890        switch (e.Op) {
 891          case TernaryExpr.Opcode.PrefixEqOp:
 892          case TernaryExpr.Opcode.PrefixNeqOp:
 0893            AddXConstraint(expr.tok, "IntOrORDINAL", e.E0.Type, "prefix-equality limit argument must be an ORDINAL or in
 0894            AddXConstraint(expr.tok, "Equatable", e.E1.Type, e.E2.Type, "arguments must have the same type (got {0} and 
 0895            AddXConstraint(expr.tok, "IsCoDatatype", e.E1.Type, "arguments to prefix equality must be codatatypes (inste
 0896            expr.Type = Type.Bool;
 0897            break;
 898          default:
 0899            Contract.Assert(false);  // unexpected ternary operator
 0900            break;
 901        }
 902
 17877903      } else if (expr is LetExpr) {
 0904        var e = (LetExpr)expr;
 0905        if (e.Exact) {
 0906          foreach (var rhs in e.RHSs) {
 0907            ResolveExpression(rhs, resolutionContext);
 0908          }
 0909          scope.PushMarker();
 0910          if (e.LHSs.Count != e.RHSs.Count) {
 0911            reporter.Error(MessageSource.Resolver, expr, "let expression must have same number of LHSs (found {0}) as RH
 0912          }
 0913          var i = 0;
 0914          foreach (var lhs in e.LHSs) {
 0915            var rhsType = i < e.RHSs.Count ? e.RHSs[i].Type : new InferredTypeProxy();
 0916            ResolveCasePattern(lhs, rhsType, resolutionContext);
 917            // Check for duplicate names now, because not until after resolving the case pattern do we know if identifie
 0918            var c = 0;
 0919            foreach (var v in lhs.Vars) {
 0920              ScopePushAndReport(scope, v, "let-variable");
 0921              c++;
 0922            }
 0923            if (c == 0) {
 924              // Every identifier-looking thing in the pattern resolved to a constructor; that is, this LHS is a constan
 0925              reporter.Error(MessageSource.Resolver, lhs.tok, "LHS is a constant literal; to be legal, it must introduce
 0926            }
 0927            i++;
 0928          }
 0929        } else {
 930          // let-such-that expression
 0931          if (e.RHSs.Count != 1) {
 0932            reporter.Error(MessageSource.Resolver, expr, "let-such-that expression must have just one RHS (found {0})", 
 0933          }
 934          // the bound variables are in scope in the RHS of a let-such-that expression
 0935          scope.PushMarker();
 0936          foreach (var lhs in e.LHSs) {
 0937            Contract.Assert(lhs.Var != null);  // the parser already checked that every LHS is a BoundVar, not a general
 0938            var v = lhs.Var;
 0939            ScopePushAndReport(scope, v, "let-variable");
 0940            ResolveType(v.tok, v.Type, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 0941          }
 0942          foreach (var rhs in e.RHSs) {
 0943            ResolveExpression(rhs, resolutionContext);
 0944            ConstrainTypeExprBool(rhs, "type of RHS of let-such-that expression must be boolean (got {0})");
 0945          }
 0946        }
 0947        ResolveExpression(e.Body, resolutionContext);
 0948        ResolveAttributes(e, resolutionContext);
 0949        scope.PopMarker();
 0950        expr.Type = e.Body.Type;
 17877951      } else if (expr is LetOrFailExpr) {
 0952        var e = (LetOrFailExpr)expr;
 0953        ResolveLetOrFailExpr(e, resolutionContext);
 17877954      } else if (expr is QuantifierExpr) {
 0955        var e = (QuantifierExpr)expr;
 0956        Contract.Assert(e.SplitQuantifier == null); // No split quantifiers during resolution
 0957        int prevErrorCount = reporter.Count(ErrorLevel.Error);
 0958        scope.PushMarker();
 0959        foreach (BoundVar v in e.BoundVars) {
 0960          ScopePushAndReport(scope, v, "bound-variable");
 0961          var option = new ResolveTypeOption(ResolveTypeOptionEnum.InferTypeProxies);
 0962          ResolveType(v.tok, v.Type, resolutionContext, option, null);
 0963        }
 0964        if (e.Range != null) {
 0965          ResolveExpression(e.Range, resolutionContext);
 0966          Contract.Assert(e.Range.Type != null);  // follows from postcondition of ResolveExpression
 0967          ConstrainTypeExprBool(e.Range, "range of quantifier must be of type bool (instead got {0})");
 0968        }
 0969        ResolveExpression(e.Term, resolutionContext);
 0970        Contract.Assert(e.Term.Type != null);  // follows from postcondition of ResolveExpression
 0971        ConstrainTypeExprBool(e.Term, "body of quantifier must be of type bool (instead got {0})");
 972        // Since the body is more likely to infer the types of the bound variables, resolve it
 973        // first (above) and only then resolve the attributes (below).
 0974        ResolveAttributes(e, resolutionContext);
 0975        scope.PopMarker();
 0976        expr.Type = Type.Bool;
 977
 17877978      } else if (expr is SetComprehension) {
 0979        var e = (SetComprehension)expr;
 0980        int prevErrorCount = reporter.Count(ErrorLevel.Error);
 0981        scope.PushMarker();
 0982        foreach (BoundVar v in e.BoundVars) {
 0983          ScopePushAndReport(scope, v, "bound-variable");
 0984          ResolveType(v.tok, v.Type, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 0985          var inferredProxy = v.Type as InferredTypeProxy;
 0986          if (inferredProxy != null) {
 0987            Contract.Assert(!inferredProxy.KeepConstraints);  // in general, this proxy is inferred to be a base type
 0988          }
 0989        }
 0990        ResolveExpression(e.Range, resolutionContext);
 0991        Contract.Assert(e.Range.Type != null);  // follows from postcondition of ResolveExpression
 0992        ConstrainTypeExprBool(e.Range, "range of comprehension must be of type bool (instead got {0})");
 0993        ResolveExpression(e.Term, resolutionContext);
 0994        Contract.Assert(e.Term.Type != null);  // follows from postcondition of ResolveExpression
 995
 0996        ResolveAttributes(e, resolutionContext);
 0997        scope.PopMarker();
 0998        expr.Type = new SetType(e.Finite, e.Term.Type);
 999
 178771000      } else if (expr is MapComprehension) {
 01001        var e = (MapComprehension)expr;
 01002        int prevErrorCount = reporter.Count(ErrorLevel.Error);
 01003        scope.PushMarker();
 01004        Contract.Assert(e.BoundVars.Count == 1 || (1 < e.BoundVars.Count && e.TermLeft != null));
 01005        foreach (BoundVar v in e.BoundVars) {
 01006          ScopePushAndReport(scope, v, "bound-variable");
 01007          ResolveType(v.tok, v.Type, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 01008          var inferredProxy = v.Type as InferredTypeProxy;
 01009          if (inferredProxy != null) {
 01010            Contract.Assert(!inferredProxy.KeepConstraints);  // in general, this proxy is inferred to be a base type
 01011          }
 01012        }
 01013        ResolveExpression(e.Range, resolutionContext);
 01014        Contract.Assert(e.Range.Type != null);  // follows from postcondition of ResolveExpression
 01015        ConstrainTypeExprBool(e.Range, "range of comprehension must be of type bool (instead got {0})");
 01016        if (e.TermLeft != null) {
 01017          ResolveExpression(e.TermLeft, resolutionContext);
 01018          Contract.Assert(e.TermLeft.Type != null);  // follows from postcondition of ResolveExpression
 01019        }
 01020        ResolveExpression(e.Term, resolutionContext);
 01021        Contract.Assert(e.Term.Type != null);  // follows from postcondition of ResolveExpression
 1022
 01023        ResolveAttributes(e, resolutionContext);
 01024        scope.PopMarker();
 01025        expr.Type = new MapType(e.Finite, e.TermLeft != null ? e.TermLeft.Type : e.BoundVars[0].Type, e.Term.Type);
 1026
 178771027      } else if (expr is LambdaExpr) {
 01028        var e = (LambdaExpr)expr;
 01029        int prevErrorCount = reporter.Count(ErrorLevel.Error);
 01030        scope.PushMarker();
 01031        foreach (BoundVar v in e.BoundVars) {
 01032          ScopePushAndReport(scope, v, "bound-variable");
 01033          ResolveType(v.tok, v.Type, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 01034        }
 1035
 01036        if (e.Range != null) {
 01037          ResolveExpression(e.Range, resolutionContext);
 01038          Contract.Assert(e.Range.Type != null);  // follows from postcondition of ResolveExpression
 01039          ConstrainTypeExprBool(e.Range, "Precondition must be boolean (got {0})");
 01040        }
 01041        foreach (var read in e.Reads) {
 01042          ResolveFrameExpression(read, FrameExpressionUse.Reads, resolutionContext);
 01043        }
 01044        ResolveExpression(e.Term, resolutionContext);
 01045        Contract.Assert(e.Term.Type != null);
 01046        scope.PopMarker();
 01047        expr.Type = SelectAppropriateArrowType(e.tok, e.BoundVars.ConvertAll(v => v.Type), e.Body.Type, e.Reads.Count !=
 178771048      } else if (expr is WildcardExpr) {
 01049        expr.Type = new SetType(true, builtIns.ObjectQ());
 178771050      } else if (expr is StmtExpr) {
 01051        var e = (StmtExpr)expr;
 01052        int prevErrorCount = reporter.Count(ErrorLevel.Error);
 1053
 01054        ResolveStatement(e.S, resolutionContext);
 01055        if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 01056          var r = e.S as UpdateStmt;
 01057          if (r != null && r.ResolvedStatements.Count == 1) {
 01058            var call = r.ResolvedStatements[0] as CallStmt;
 01059            if (call.Method is TwoStateLemma && !resolutionContext.IsTwoState) {
 01060              reporter.Error(MessageSource.Resolver, call, "two-state lemmas can only be used in two-state contexts");
 01061            }
 01062          }
 01063        }
 1064
 01065        ResolveExpression(e.E, resolutionContext);
 01066        Contract.Assert(e.E.Type != null);  // follows from postcondition of ResolveExpression
 01067        expr.Type = e.E.Type;
 1068
 324901069      } else if (expr is ITEExpr) {
 146131070        ITEExpr e = (ITEExpr)expr;
 146131071        ResolveExpression(e.Test, resolutionContext);
 146131072        Contract.Assert(e.Test.Type != null);  // follows from postcondition of ResolveExpression
 146131073        ResolveExpression(e.Thn, resolutionContext);
 146131074        Contract.Assert(e.Thn.Type != null);  // follows from postcondition of ResolveExpression
 146131075        ResolveExpression(e.Els, resolutionContext);
 146131076        Contract.Assert(e.Els.Type != null);  // follows from postcondition of ResolveExpression
 146131077        ConstrainTypeExprBool(e.Test, "guard condition in if-then-else expression must be a boolean (instead got {0})");
 146131078        expr.Type = new InferredTypeProxy();
 146131079        ConstrainSubtypeRelation(expr.Type, e.Thn.Type, expr, "the two branches of an if-then-else expression must have 
 146131080        ConstrainSubtypeRelation(expr.Type, e.Els.Type, expr, "the two branches of an if-then-else expression must have 
 1081
 211411082      } else if (expr is NestedMatchExpr nestedMatchExpr) {
 32641083        ResolveNestedMatchExpr(nestedMatchExpr, resolutionContext);
 32641084      } else {
 01085        Contract.Assert(false); throw new cce.UnreachableException();  // unexpected expression
 1086      }
 1087
 5946531088      if (expr.Type == null) {
 1089        // some resolution error occurred
 01090        expr.Type = new InferredTypeProxy();
 01091      }
 1092
 5946531093      DominatingStatementLabels.PopMarker();
 7594801094    }
 1095
 71501096    void ResolveTypeParameters(List<TypeParameter/*!*/>/*!*/ tparams, bool emitErrors, TypeParameter.ParentType/*!*/ par
 1097      Contract.Requires(tparams != null);
 1098      Contract.Requires(parent != null);
 1099      // push non-duplicated type parameter names
 71501100      int index = 0;
 280021101      foreach (TypeParameter tp in tparams) {
 32201102        if (emitErrors) {
 1103          // we're seeing this TypeParameter for the first time
 10361104          tp.Parent = parent;
 10361105          tp.PositionalIndex = index;
 10361106        }
 21841107        var r = allTypeParameters.Push(tp.Name, tp);
 32201108        if (emitErrors) {
 10361109          if (r == Scope<TypeParameter>.PushResult.Duplicate) {
 01110            reporter.Error(MessageSource.Resolver, ErrorRegistry.NoneId, tp, "Duplicate type-parameter name: {0}", tp.Na
 10361111          } else if (r == Scope<TypeParameter>.PushResult.Shadow) {
 01112            reporter.Warning(MessageSource.Resolver, ErrorRegistry.NoneId, tp.tok, "Shadowed type-parameter name: {0}", 
 01113          }
 10361114        }
 21841115      }
 71501116    }
 1117
 956011118    private bool ConstrainSubtypeRelation(Type super, Type sub, Expression exprForToken, string msg, params object[] msg
 1119      Contract.Requires(sub != null);
 1120      Contract.Requires(super != null);
 1121      Contract.Requires(exprForToken != null);
 1122      Contract.Requires(msg != null);
 1123      Contract.Requires(msgArgs != null);
 956011124      return ConstrainSubtypeRelation(super, sub, exprForToken.tok, msg, msgArgs);
 956011125    }
 1126
 202891127    public void ConstrainTypeExprBool(Expression e, string msg) {
 1128      Contract.Requires(e != null);
 1129      Contract.Requires(msg != null);  // expected to have a {0} part
 202891130      ConstrainSubtypeRelation(Type.Bool, e.Type, e, msg, e.Type);
 202891131    }
 1132
 2969521133    public bool ConstrainSubtypeRelation(Type super, Type sub, IToken tok, string msg, params object[] msgArgs) {
 1134      Contract.Requires(sub != null);
 1135      Contract.Requires(super != null);
 1136      Contract.Requires(tok != null);
 1137      Contract.Requires(msg != null);
 1138      Contract.Requires(msgArgs != null);
 2969521139      return ConstrainSubtypeRelation(super, sub, new TypeConstraint.ErrorMsgWithToken(tok, msg, msgArgs));
 2969521140    }
 1141
 1137371142    private void ConstrainAssignable(NonProxyType lhs, Type rhs, TypeConstraint.ErrorMsg errMsg, out bool moreXConstrain
 1143      Contract.Requires(lhs != null);
 1144      Contract.Requires(rhs != null);
 1145      Contract.Requires(errMsg != null);
 1146
 1137371147      DetermineRootLeaf(lhs, out var isRoot, out _, out _, out _);
 2188591148      if (isRoot) {
 1051221149        ConstrainSubtypeRelation(lhs, rhs, errMsg, true, allowDecisions);
 1051221150        moreXConstraints = false;
 1137371151      } else {
 86151152        var lhsWithProxyArgs = Type.HeadWithProxyArgs(lhs);
 86151153        ConstrainSubtypeRelation(lhsWithProxyArgs, rhs, errMsg, false, allowDecisions);
 86151154        ConstrainAssignableTypeArgs(lhs, lhsWithProxyArgs.TypeArgs, lhs.TypeArgs, errMsg, out moreXConstraints);
 168151155        if (lhs.AsCollectionType == null) {
 82001156          var sameHead = Type.SameHead(lhs, rhs);
 82001157          if (!sameHead && lhs is UserDefinedType udtLhs && rhs is UserDefinedType udtRhs) {
 1158            // also allow the case where lhs is a possibly-null type and rhs is a non-null type
 01159            sameHead = udtLhs.ResolvedClass == (udtRhs.ResolvedClass as NonNullTypeDecl)?.Class;
 01160          }
 158651161          if (sameHead) {
 76651162            ConstrainAssignableTypeArgs(lhs, lhs.TypeArgs, rhs.TypeArgs, errMsg, out var more2);
 76651163            moreXConstraints = moreXConstraints || more2;
 76651164          }
 82001165        }
 86151166      }
 1137371167    }
 1168
 217201169    private void ConstrainAssignableTypeArgs(Type typeHead, List<Type> A, List<Type> B, TypeConstraint.ErrorMsg errMsg, 
 1170      Contract.Requires(typeHead != null);
 1171      Contract.Requires(A != null);
 1172      Contract.Requires(B != null);
 1173      Contract.Requires(A.Count == B.Count);
 1174      Contract.Requires(errMsg != null);
 1175
 217201176      var tok = errMsg.Tok;
 234551177      if (B.Count == 0) {
 1178        // all done
 17351179        moreXConstraints = false;
 226501180      } else if (typeHead is MapType) {
 9301181        var em = new TypeConstraint.ErrorMsgWithBase(errMsg, "covariance for type parameter at index 0 expects {1} <: {0
 9301182        AddAssignableConstraint(tok, A[0], B[0], em);
 9301183        em = new TypeConstraint.ErrorMsgWithBase(errMsg, "covariance for type parameter at index 1 expects {1} <: {0}", 
 9301184        AddAssignableConstraint(tok, A[1], B[1], em);
 9301185        moreXConstraints = true;
 231101186      } else if (typeHead is CollectionType) {
 31251187        var em = new TypeConstraint.ErrorMsgWithBase(errMsg, "covariance for type parameter expects {1} <: {0}", A[0], B
 31251188        AddAssignableConstraint(tok, A[0], B[0], em);
 31251189        moreXConstraints = true;
 190551190      } else {
 159301191        var udt = (UserDefinedType)typeHead;  // note, collections, maps, and user-defined types are the only one with T
 159301192        var cl = udt.ResolvedClass;
 159301193        Contract.Assert(cl != null);
 159301194        Contract.Assert(cl.TypeArgs.Count == B.Count);
 159301195        moreXConstraints = false;
 858751196        for (int i = 0; i < B.Count; i++) {
 180051197          var msgFormat = "variance for type parameter" + (B.Count == 1 ? "" : " at index " + i) + " expects {0} {1} {2}
 211351198          if (cl.TypeArgs[i].Variance == TypeParameter.TPVariance.Co) {
 31301199            var em = new TypeConstraint.ErrorMsgWithBase(errMsg, "co" + msgFormat, A[i], ":>", B[i]);
 31301200            AddAssignableConstraint(tok, A[i], B[i], em);
 31301201            moreXConstraints = true;
 180051202          } else if (cl.TypeArgs[i].Variance == TypeParameter.TPVariance.Contra) {
 01203            var em = new TypeConstraint.ErrorMsgWithBase(errMsg, "contra" + msgFormat, A[i], "<:", B[i]);
 01204            AddAssignableConstraint(tok, B[i], A[i], em);
 01205            moreXConstraints = true;
 148751206          } else {
 148751207            var em = new TypeConstraint.ErrorMsgWithBase(errMsg, "non" + msgFormat, A[i], "=", B[i]);
 148751208            ConstrainSubtypeRelation_Equal(A[i], B[i], em);
 148751209          }
 180051210        }
 159301211      }
 217201212    }
 1213
 1214    /// <summary>
 1215    /// Adds the subtyping constraint that "a" and "b" are the same type.
 1216    /// </summary>
 163141217    private void ConstrainSubtypeRelation_Equal(Type a, Type b, TypeConstraint.ErrorMsg errMsg) {
 1218      Contract.Requires(a != null);
 1219      Contract.Requires(b != null);
 1220      Contract.Requires(errMsg != null);
 1221
 163141222      var proxy = a.Normalize() as TypeProxy;
 244541223      if (proxy != null && proxy.T == null && !Reaches(b, proxy, 1, new HashSet<TypeProxy>())) {
 81401224        if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 01225          Options.OutputWriter.WriteLine("DEBUG: (invariance) assigning proxy {0}.T := {1}", proxy, b);
 01226        }
 81401227        proxy.T = b;
 81401228      }
 163141229      proxy = b.Normalize() as TypeProxy;
 165141230      if (proxy != null && proxy.T == null && !Reaches(a, proxy, 1, new HashSet<TypeProxy>())) {
 2001231        if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 01232          Options.OutputWriter.WriteLine("DEBUG: (invariance) assigning proxy {0}.T := {1}", proxy, a);
 01233        }
 2001234        proxy.T = a;
 2001235      }
 1236
 163141237      ConstrainSubtypeRelation(a, b, errMsg, true);
 163141238      ConstrainSubtypeRelation(b, a, errMsg, true);
 163141239    }
 1240
 1241    /// <summary>
 1242    /// Adds the subtyping constraint that "sub" is a subtype of "super".
 1243    /// If this constraint seems feasible, returns "true".  Otherwise, prints error message (either "errMsg" or somethin
 1244    /// more specific) and returns "false".
 1245    /// Note, if in doubt, this method can return "true", because the constraints will be checked for sure at a later st
 1246    /// </summary>
 5986761247    private bool ConstrainSubtypeRelation(Type super, Type sub, TypeConstraint.ErrorMsg errMsg, bool keepConstraints = f
 1248      Contract.Requires(sub != null);
 1249      Contract.Requires(super != null);
 1250      Contract.Requires(errMsg != null);
 1251
 7805291252      if (!keepConstraints && super is InferredTypeProxy) {
 1818531253        var ip = (InferredTypeProxy)super;
 2291081254        if (ip.KeepConstraints) {
 472551255          keepConstraints = true;
 472551256        }
 1818531257      }
 7503431258      if (!keepConstraints && sub is InferredTypeProxy) {
 1516671259        var ip = (InferredTypeProxy)sub;
 1587931260        if (ip.KeepConstraints) {
 71261261          keepConstraints = true;
 71261262        }
 1516671263      }
 1264
 5986761265      super = super.NormalizeExpand(keepConstraints);
 5986761266      sub = sub.NormalizeExpand(keepConstraints);
 5986761267      var c = new TypeConstraint(super, sub, errMsg, keepConstraints);
 5986761268      AllTypeConstraints.Add(c);
 5986761269      return ConstrainSubtypeRelation_Aux(super, sub, c, keepConstraints, allowDecisions);
 5986761270    }
 5986761271    private bool ConstrainSubtypeRelation_Aux(Type super, Type sub, TypeConstraint c, bool keepConstraints, bool allowDe
 1272      Contract.Requires(sub != null);
 1273      Contract.Requires(!(sub is TypeProxy) || ((TypeProxy)sub).T == null);  // caller is expected to have Normalized aw
 1274      Contract.Requires(super != null);
 1275      Contract.Requires(!(super is TypeProxy) || ((TypeProxy)super).T == null);  // caller is expected to have Normalize
 1276      Contract.Requires(c != null);
 1277
 7816041278      if (object.ReferenceEquals(super, sub)) {
 1829281279        return true;
 4809561280      } else if (super is TypeProxy && sub is TypeProxy) {
 1281        // both are proxies
 652081282        ((TypeProxy)sub).AddSupertype(c);
 652081283        ((TypeProxy)super).AddSubtype(c);
 652081284        return true;
 5010831285      } else if (sub is TypeProxy) {
 1505431286        var proxy = (TypeProxy)sub;
 1505431287        proxy.AddSupertype(c);
 1505431288        AssignKnownEnd(proxy, keepConstraints, allowDecisions);
 1505431289        return true;
 2789641290      } else if (super is TypeProxy) {
 789671291        var proxy = (TypeProxy)super;
 789671292        proxy.AddSubtype(c);
 789671293        AssignKnownEnd(proxy, keepConstraints, allowDecisions);
 789671294        return true;
 1210301295      } else {
 1296        // two non-proxy types
 1297        // set "headSymbolsAgree" to "false" if it's clear the head symbols couldn't be the same; "true" means they may 
 1210301298        bool headSymbolsAgree = Type.IsHeadSupertypeOf(super.NormalizeExpand(keepConstraints), sub);
 1210301299        if (!headSymbolsAgree) {
 01300          c.FlagAsError(this);
 01301          return false;
 1302        }
 1303        // TODO: inspect type parameters in order to produce some error messages sooner
 1210301304        return true;
 1305      }
 5986761306    }
 1307
 1308    /// <summary>
 1309    /// "root" says that the type is a non-artificial type (that is, not an ArtificialType) with no proper supertypes.
 1310    /// "leaf" says that the only possible proper subtypes are subset types of the type. Thus, the only
 1311    /// types that are not leaf types are traits and artificial types.
 1312    /// The "headIs" versions speak only about the head symbols, so it is possible that the given
 1313    /// type arguments would change the root/leaf status of the entire type.
 1314    /// </summary>
 225211451315    void DetermineRootLeaf(Type t, out bool isRoot, out bool isLeaf, out bool headIsRoot, out bool headIsLeaf) {
 1316      Contract.Requires(t != null);
 1317      Contract.Ensures(!Contract.ValueAtReturn(out isRoot) || Contract.ValueAtReturn(out headIsRoot)); // isRoot ==> hea
 1318      Contract.Ensures(!Contract.ValueAtReturn(out isLeaf) || Contract.ValueAtReturn(out headIsLeaf)); // isLeaf ==> hea
 225211451319      t = t.NormalizeExpandKeepConstraints();
 225212571320      if (t.IsObjectQ) {
 2241321        isRoot = true; isLeaf = false;
 2241322        headIsRoot = true; headIsLeaf = false;
 225211451323      } else if (t is ArrowType) {
 01324        var arr = (ArrowType)t;
 01325        headIsRoot = true; headIsLeaf = true;  // these are definitely true
 01326        isRoot = true; isLeaf = true;  // set these to true until proven otherwise
 01327        Contract.Assert(arr.Arity + 1 == arr.TypeArgs.Count);
 01328        for (int i = 0; i < arr.TypeArgs.Count; i++) {
 01329          var arg = arr.TypeArgs[i];
 01330          DetermineRootLeaf(arg, out var r, out var l, out _, out _);
 01331          if (i < arr.Arity) {
 01332            isRoot &= l; isLeaf &= r;  // argument types are contravariant
 01333          } else {
 01334            isRoot &= r; isLeaf &= l;  // result type is covariant
 01335          }
 01336        }
 231228381337      } else if (t is UserDefinedType) {
 6018051338        var udt = (UserDefinedType)t;
 6018051339        var cl = udt.ResolvedClass;
 12036101340        if (cl != null) {
 6035171341          if (cl is TypeParameter) {
 17121342            var tp = udt.AsTypeParameter;
 17121343            Contract.Assert(tp != null);
 34241344            headIsRoot = true; headIsLeaf = true;  // all type parameters are non-variant
 10215501345          } else if (cl is SubsetTypeDecl) {
 8394901346            headIsRoot = false; headIsLeaf = true;
 6000931347          } else if (cl is NewtypeDecl) {
 01348            headIsRoot = true; headIsLeaf = true;
 1803481349          } else if (cl is TraitDecl) {
 01350            headIsRoot = false; headIsLeaf = false;
 3226801351          } else if (cl is ClassDecl) {
 2846641352            headIsRoot = false; headIsLeaf = true;
 1803481353          } else if (cl is AbstractTypeDecl) {
 01354            headIsRoot = true; headIsLeaf = true;
 380161355          } else if (cl is InternalTypeSynonymDecl) {
 01356            Contract.Assert(object.ReferenceEquals(t, t.NormalizeExpand())); // should be opaque in scope
 01357            headIsRoot = true; headIsLeaf = true;
 380161358          } else {
 380161359            Contract.Assert(cl is DatatypeDecl);
 760321360            headIsRoot = true; headIsLeaf = true;
 380161361          }
 1362          // for "isRoot" and "isLeaf", also take into consideration the root/leaf status of type arguments
 12036101363          isRoot = headIsRoot; isLeaf = headIsLeaf;
 6018051364          Contract.Assert(udt.TypeArgs.Count == cl.TypeArgs.Count);
 31002221365          for (int i = 0; i < udt.TypeArgs.Count; i++) {
 6322041366            var variance = cl.TypeArgs[i].Variance;
 6898291367            if (variance != TypeParameter.TPVariance.Non) {
 576251368              DetermineRootLeaf(udt.TypeArgs[i], out var r, out var l, out _, out _);
 1369              // isRoot and isLeaf aren't duals, so Co and Contra require separate consideration beyond inversion.
 576251370              switch (variance) {
 2305001371                case TypeParameter.TPVariance.Co: { isRoot &= r; isLeaf &= l; break; }
 1372                // A invariably constructible subtype becomes a supertype, and thus the enclosing type is never a root.
 01373                case TypeParameter.TPVariance.Contra: { isRoot &= false; isLeaf &= r; break; }
 1374              }
 576251375            }
 6322041376          }
 6018051377        } else {
 01378          isRoot = false; isLeaf = false;  // don't know
 01379          headIsRoot = false; headIsLeaf = false;
 01380        }
 229315161381      } else if (t.IsBoolType || t.IsCharType || t.IsIntegerType || t.IsRealType || t.AsNewtype != null || t.IsBitVector
 8209661382        isRoot = true; isLeaf = true;
 8209661383        headIsRoot = true; headIsLeaf = true;
 219192281384      } else if (t is ArtificialType) {
 01385        isRoot = false; isLeaf = false;
 01386        headIsRoot = false; headIsLeaf = false;
 215258841387      } else if (t is MapType) {  // map, imap
 171391388        Contract.Assert(t.TypeArgs.Count == 2);
 171391389        DetermineRootLeaf(t.TypeArgs[0], out var r0, out _, out _, out _);
 171391390        DetermineRootLeaf(t.TypeArgs[1], out var r1, out _, out _, out _);
 342781391        isRoot = r0 & r1; isLeaf = r0 & r1;  // map types are covariant in both type arguments
 342781392        headIsRoot = true; headIsLeaf = true;
 215387181393      } else if (t is CollectionType) {  // set, iset, multiset, seq
 299731394        Contract.Assert(t.TypeArgs.Count == 1);
 299731395        DetermineRootLeaf(t.TypeArgs[0], out isRoot, out isLeaf, out _, out _);  // type is covariant is type argument
 599461396        headIsRoot = true; headIsLeaf = true;
 214916061397      } else {
 429232661398        isRoot = false; isLeaf = false;  // don't know
 429232661399        headIsRoot = false; headIsLeaf = false;
 214616331400      }
 225211451401    }
 1402
 1121403    int _recursionDepth = 0;
 2071571404    private bool AssignProxyAndHandleItsConstraints(TypeProxy proxy, Type t, bool keepConstraints = false) {
 1405      Contract.Requires(proxy != null);
 1406      Contract.Requires(proxy.T == null);
 1407      Contract.Requires(t != null);
 1408      Contract.Requires(!(t is TypeProxy));
 1409      Contract.Requires(!(t is ArtificialType));
 2071571410      if (_recursionDepth == 20000) {
 01411        Contract.Assume(false);  // possible infinite recursion
 01412      }
 2071571413      _recursionDepth++;
 2071571414      var b = AssignProxyAndHandleItsConstraints_aux(proxy, t, keepConstraints);
 2071571415      _recursionDepth--;
 2071571416      return b;
 2071571417    }
 1418    /// <summary>
 1419    /// This method is called if "proxy" is an unassigned proxy and "t" is a type whose head symbol is known.
 1420    /// It always sets "proxy.T" to "t".
 1421    /// Then, it deals with the constraints of "proxy" as follows:
 1422    /// * If the constraint compares "t" with a non-proxy with a head comparable with that of "t",
 1423    ///   then add constraints that the type arguments satisfy the desired subtyping constraint
 1424    /// * If the constraint compares "t" with a non-proxy with a head not comparable with that of "t",
 1425    ///   then report an error
 1426    /// * If the constraint compares "t" with a proxy, then (depending on the constraint and "t") attempt
 1427    ///   to recursively set it
 1428    /// After this process, the proxy's .Supertypes and .Subtypes lists of constraints are no longer needed.
 1429    /// If anything is found to be infeasible, "false" is returned (and the propagation may be interrupted);
 1430    /// otherwise, "true" is returned.
 1431    /// </summary>
 2071571432    private bool AssignProxyAndHandleItsConstraints_aux(TypeProxy proxy, Type t, bool keepConstraints = false) {
 1433      Contract.Requires(proxy != null);
 1434      Contract.Requires(proxy.T == null);
 1435      Contract.Requires(t != null);
 1436      Contract.Requires(!(t is TypeProxy));
 1437      Contract.Requires(!(t is ArtificialType));
 1438
 2071571439      t = keepConstraints ? t.Normalize() : t.NormalizeExpand();
 1440      // never violate the type constraint of a literal expression
 2071571441      var followedRequestedAssignment = true;
 9479431442      foreach (var su in proxy.Supertypes) {
 2112451443        if (su is IntVarietiesSupertype) {
 713471444          var fam = TypeProxy.GetFamily(t);
 1426941445          if (fam == TypeProxy.Family.IntLike || fam == TypeProxy.Family.BitVector || fam == TypeProxy.Family.Ordinal) {
 1446            // good, let's continue with the request to equate the proxy with t
 1447            // unless...
 713471448            if (t != t.NormalizeExpand()) {
 1449              // force the type to be a base type
 01450              if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 01451                Options.OutputWriter.WriteLine("DEBUG: hijacking {0}.T := {1} to instead assign {2}", proxy, t, t.Normal
 01452              }
 01453              t = t.NormalizeExpand();
 01454              followedRequestedAssignment = false;
 01455            }
 713471456          } else {
 1457            // hijack the setting of proxy; to do that, we decide on a particular int variety now
 01458            if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 01459              Options.OutputWriter.WriteLine("DEBUG: hijacking {0}.T := {1} to instead assign {2}", proxy, t, Type.Int);
 01460            }
 01461            t = Type.Int;
 01462            followedRequestedAssignment = false;
 01463          }
 713471464          break;
 904261465        } else if (su is RealVarietiesSupertype) {
 437501466          if (TypeProxy.GetFamily(t) == TypeProxy.Family.RealLike) {
 1467            // good, let's continue with the request to equate the proxy with t
 1468            // unless...
 218751469            if (t != t.NormalizeExpand()) {
 1470              // force the type to be a base type
 01471              if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 01472                Options.OutputWriter.WriteLine("DEBUG: hijacking {0}.T := {1} to instead assign {2}", proxy, t, t.Normal
 01473              }
 01474              t = t.NormalizeExpand();
 01475              followedRequestedAssignment = false;
 01476            }
 218751477          } else {
 1478            // hijack the setting of proxy; to do that, we decide on a particular real variety now
 01479            if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 01480              Options.OutputWriter.WriteLine("DEBUG: hijacking {0}.T := {1} to instead assign {2}", proxy, t, Type.Real)
 01481            }
 01482            t = Type.Real;
 01483            followedRequestedAssignment = false;
 01484          }
 218751485          break;
 1486        }
 466761487      }
 1488      // set proxy.T right away, so that we can freely recurse without having to worry about infinite recursion
 2071571489      if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 01490        Options.OutputWriter.WriteLine("DEBUG: setting proxy {0}.T := {1}", proxy, t);
 01491      }
 2071571492      proxy.T = t;
 1493
 1494      // check feasibility
 2071571495      DetermineRootLeaf(t, out var isRoot, out var isLeaf, out _, out _);
 1496      // propagate up
 12384541497      foreach (var c in proxy.SupertypeConstraints) {
 2056611498        var u = keepConstraints ? c.Super.NormalizeExpandKeepConstraints() : c.Super.NormalizeExpand();
 4076521499        if (!(u is TypeProxy)) {
 2019911500          ImposeSubtypingConstraint(u, t, c.ErrMsg);
 2093061501        } else if (isRoot) {
 1502          // If t is a root, we might as well constrain u now.  Otherwise, we'll wait until the .Subtype constraint of u
 36451503          AssignProxyAndHandleItsConstraints((TypeProxy)u, t, keepConstraints);
 36451504        }
 2056611505      }
 1506      // propagate down
 10387111507      foreach (var c in proxy.SubtypeConstraints) {
 1390801508        var u = keepConstraints ? c.Sub.NormalizeExpandKeepConstraints() : c.Sub.NormalizeExpand();
 1390801509        Contract.Assert(!TypeProxy.IsSupertypeOfLiteral(u));  // these should only appear among .Supertypes
 2243421510        if (!(u is TypeProxy)) {
 852621511          ImposeSubtypingConstraint(t, u, c.ErrMsg);
 1924081512        } else if (isLeaf) {
 1513          // If t is a leaf (no pun intended), we might as well constrain u now.  Otherwise, we'll wait until the .Super
 533281514          AssignProxyAndHandleItsConstraints((TypeProxy)u, t, keepConstraints);
 533281515        }
 1390801516      }
 1517
 2071571518      return followedRequestedAssignment;
 2071571519    }
 1520
 1521    /// <summary>
 1522    /// Impose constraints that "sub" is a subtype of "super", returning "false" if this leads to an overconstrained sit
 1523    /// In most cases, "sub" being a subtype of "super" means that "sub" and "super" have the same head symbol and, ther
 1524    /// same number of type arguments. Depending on the polarities of the type parameters, the corresponding arguments
 1525    /// of "sub" and "super" must be in co-, in-, or contra-variant relationships to each other.
 1526    /// There are two ways "sub" can be a subtype of "super" without the two having the same head symbol.
 1527    /// One way is that "sub" is a subset type. In this case, the method starts by moving "sub" up toward "super".
 1528    /// The other way is that "super" is a trait (possibly
 1529    /// the trait "object").  By a current restriction in Dafny's type system, traits have no type parameters, so in thi
 1530    /// suffices to check that the head symbol of "super" is something that derives from "sub".
 1531    /// </summary>
 4122991532    private bool ImposeSubtypingConstraint(Type super, Type sub, TypeConstraint.ErrorMsg errorMsg) {
 1533      Contract.Requires(super != null && !(super is TypeProxy));
 1534      Contract.Requires(sub != null && !(sub is TypeProxy));
 1535      Contract.Requires(errorMsg != null);
 4122991536      super = super.NormalizeExpandKeepConstraints();
 4122991537      sub = sub.NormalizeExpandKeepConstraints();
 4122991538      List<int> polarities = ConstrainTypeHead_Recursive(super, ref sub);
 4122991539      if (polarities == null) {
 01540        errorMsg.FlagAsError(this);
 01541        return false;
 1542      }
 4122991543      bool keepConstraints = KeepConstraints(super, sub);
 4122991544      var p = polarities.Count;
 4122991545      Contract.Assert(p == super.TypeArgs.Count);  // postcondition of ConstrainTypeHead
 4122991546      Contract.Assert(p == 0 || sub.TypeArgs.Count == super.TypeArgs.Count);  // postcondition of ConstrainTypeHead
 10448671547      for (int i = 0; i < p; i++) {
 734231548        var pol = polarities[i];
 734231549        var tp = p == 1 ? "" : " " + i;
 734231550        var errMsg = new TypeConstraint.ErrorMsgWithBase(errorMsg,
 734231551          pol < 0 ? "contravariant type parameter{0} would require {1} <: {2}" :
 734231552          pol > 0 ? "covariant type parameter{0} would require {2} <: {1}" :
 734231553          "non-variant type parameter{0} would require {1} = {2}",
 734231554          tp, super.TypeArgs[i], sub.TypeArgs[i]);
 1468461555        if (pol >= 0) {
 734231556          if (!ConstrainSubtypeRelation(super.TypeArgs[i], sub.TypeArgs[i], errMsg, keepConstraints)) {
 01557            return false;
 1558          }
 734231559        }
 805291560        if (pol <= 0) {
 71061561          if (!ConstrainSubtypeRelation(sub.TypeArgs[i], super.TypeArgs[i], errMsg, keepConstraints)) {
 01562            return false;
 1563          }
 71061564        }
 734231565      }
 4122991566      return true;
 4122991567    }
 1568
 1569    /// <summary>
 1570    /// This is a more liberal version of "ConstrainTypeHead" below. It is willing to move "sub"
 1571    /// upward toward its parents until it finds a head that matches "super", if any.
 1572    /// </summary>
 4122991573    private static List<int> ConstrainTypeHead_Recursive(Type super, ref Type sub) {
 1574      Contract.Requires(super != null);
 1575      Contract.Requires(sub != null);
 1576
 4122991577      super = super.NormalizeExpandKeepConstraints();
 4122991578      sub = sub.NormalizeExpandKeepConstraints();
 1579
 4122991580      var polarities = ConstrainTypeHead(super, sub);
 8245981581      if (polarities != null) {
 4122991582        return polarities;
 1583      }
 1584
 01585      foreach (var subParentType in sub.ParentTypes()) {
 01586        sub = subParentType;
 01587        polarities = ConstrainTypeHead_Recursive(super, ref sub);
 01588        if (polarities != null) {
 01589          return polarities;
 1590        }
 01591      }
 1592
 01593      return null;
 4122991594    }
 1595
 1596    /// <summary>
 1597    /// Determines if the head of "sub" can be a subtype of "super".
 1598    /// If this is not possible, null is returned.
 1599    /// If it is possible, return a list of polarities, one for each type argument of "sub".  Polarities
 1600    /// indicate:
 1601    ///     +1  co-variant
 1602    ///      0  invariant
 1603    ///     -1  contra-variant
 1604    /// "sub" is of some type that can (in general) have type parameters.
 1605    /// See also note about Dafny's current type system in the description of method "ImposeSubtypingConstraint".
 1606    /// </summary>
 4122991607    private static List<int> ConstrainTypeHead(Type super, Type sub) {
 1608      Contract.Requires(super != null && !(super is TypeProxy));
 1609      Contract.Requires(sub != null && !(sub is TypeProxy));
 5686471610      if (super is IntVarietiesSupertype) {
 1563481611        var famSub = TypeProxy.GetFamily(sub);
 3126961612        if (famSub == TypeProxy.Family.IntLike || famSub == TypeProxy.Family.BitVector || famSub == TypeProxy.Family.Ord
 1563481613          return new List<int>();
 01614        } else {
 01615          return null;
 1616        }
 2996261617      } else if (super is RealVarietiesSupertype) {
 873501618        if (TypeProxy.GetFamily(sub) == TypeProxy.Family.RealLike || super.Equals(sub)) {
 436751619          return new List<int>();
 01620        } else {
 01621          return null;
 1622        }
 1623      }
 2122761624      switch (TypeProxy.GetFamily(super)) {
 1625        case TypeProxy.Family.Bool:
 1626        case TypeProxy.Family.Char:
 1627        case TypeProxy.Family.IntLike:
 1628        case TypeProxy.Family.RealLike:
 1629        case TypeProxy.Family.Ordinal:
 1630        case TypeProxy.Family.BitVector:
 3314521631          if (super.Equals(sub)) {
 1657261632            if (sub is UserDefinedType subUserDefinedType) {
 01633              return subUserDefinedType.ResolvedClass.TypeArgs.ConvertAll(tp => TypeParameter.Direction(tp.Variance));
 1657261634            } else {
 1657261635              return new List<int>();
 1636            }
 01637          } else {
 01638            return null;
 1639          }
 1640        case TypeProxy.Family.ValueType:
 1641        case TypeProxy.Family.Ref:
 1642        case TypeProxy.Family.Opaque:
 465501643          break;  // more elaborate work below
 1644        case TypeProxy.Family.Unknown:
 01645          return null;
 1646        default:
 01647          Contract.Assert(false);  // unexpected type (the precondition of ConstrainTypeHead says "no proxies")
 01648          return null;  // please compiler
 1649      }
 514351650      if (super is SetType) {
 48851651        var tt = (SetType)super;
 48851652        var uu = sub as SetType;
 48851653        return uu != null && tt.Finite == uu.Finite ? new List<int> { 1 } : null;
 520651654      } else if (super is SeqType) {
 104001655        return sub is SeqType ? new List<int> { 1 } : null;
 350651656      } else if (super is MultiSetType) {
 38001657        return sub is MultiSetType ? new List<int> { 1 } : null;
 379311658      } else if (super is MapType) {
 104661659        var tt = (MapType)super;
 104661660        var uu = sub as MapType;
 104661661        return uu != null && tt.Finite == uu.Finite ? new List<int> { 1, 1 } : null;
 169991662      } else if (super.IsObjectQ) {
 01663        return sub.IsRefType ? new List<int>() : null;
 169991664      } else {
 1665        // The only remaining cases are that "super" is a (co)datatype, abstract type, or non-object trait/class.
 1666        // In each of these cases, "super" is a UserDefinedType.
 169991667        var udfSuper = (UserDefinedType)super;
 169991668        var clSuper = udfSuper.ResolvedClass;
 169991669        if (clSuper == null) {
 01670          Contract.Assert(super.TypeArgs.Count == 0);
 01671          if (super.IsTypeParameter) {
 1672            // we're looking at a type parameter
 01673            return super.AsTypeParameter == sub.AsTypeParameter ? new List<int>() : null;
 01674          } else {
 01675            Contract.Assert(super.IsInternalTypeSynonym);
 01676            return super.AsInternalTypeSynonym == sub.AsInternalTypeSynonym ? new List<int>() : null;
 1677          }
 1678        }
 169991679        var udfSub = sub as UserDefinedType;
 169991680        var clSub = udfSub == null ? null : udfSub.ResolvedClass;
 169991681        if (clSub == null) {
 01682          return null;
 339981683        } else if (clSuper == clSub) {
 1684          // good
 169991685          var polarities = new List<int>();
 169991686          Contract.Assert(clSuper.TypeArgs.Count == udfSuper.TypeArgs.Count);
 169991687          Contract.Assert(clSuper.TypeArgs.Count == udfSub.TypeArgs.Count);
 1512151688          foreach (var tp in clSuper.TypeArgs) {
 334061689            var polarity = TypeParameter.Direction(tp.Variance);
 334061690            polarities.Add(polarity);
 334061691          }
 1692
 169991693          return polarities;
 01694        } else if (udfSub.IsRefType && super.IsObjectQ) {
 01695          return new List<int>();
 01696        } else if (udfSub.IsNonNullRefType && super.IsObject) {
 01697          return new List<int>();
 01698        } else {
 01699          return null;
 1700        }
 1701      }
 4122991702    }
 4122991703    private static bool KeepConstraints(Type super, Type sub) {
 1704      Contract.Requires(super != null && !(super is TypeProxy));
 1705      Contract.Requires(sub != null && !(sub is TypeProxy));
 5686471706      if (super is IntVarietiesSupertype) {
 1563481707        return false;
 2996261708      } else if (super is RealVarietiesSupertype) {
 436751709        return false;
 1710      }
 2122761711      switch (TypeProxy.GetFamily(super)) {
 1712        case TypeProxy.Family.Bool:
 1713        case TypeProxy.Family.Char:
 1714        case TypeProxy.Family.IntLike:
 1715        case TypeProxy.Family.RealLike:
 1716        case TypeProxy.Family.Ordinal:
 1717        case TypeProxy.Family.BitVector:
 1657261718          return false;
 1719        case TypeProxy.Family.ValueType:
 1720        case TypeProxy.Family.Ref:
 1721        case TypeProxy.Family.Opaque:
 465501722          break;  // more elaborate work below
 1723        case TypeProxy.Family.Unknown:
 01724          return false;
 1725      }
 761011726      if (super is SetType || super is SeqType || super is MultiSetType || super is MapType) {
 295511727        return true;
 169991728      } else if (super is ArrowType) {
 01729        return false;
 169991730      } else if (super.IsObjectQ) {
 01731        return false;
 169991732      } else {
 1733        // super is UserDefinedType
 169991734        return true;
 1735      }
 4122991736    }
 1737
 1121738    public List<TypeConstraint> AllTypeConstraints = new List<TypeConstraint>();
 1121739    public List<XConstraint> AllXConstraints = new List<XConstraint>();
 1740
 1741    public class XConstraint {
 1742      public readonly IToken tok;
 1743      public readonly string ConstraintName;
 1744      public readonly Type[] Types;
 1745      public readonly TypeConstraint.ErrorMsg errorMsg;
 5135761746      public XConstraint(IToken tok, string constraintName, Type[] types, TypeConstraint.ErrorMsg errMsg) {
 1747        Contract.Requires(tok != null);
 1748        Contract.Requires(constraintName != null);
 1749        Contract.Requires(types != null);
 1750        Contract.Requires(errMsg != null);
 2567881751        this.tok = tok;
 2567881752        ConstraintName = constraintName;
 2567881753        Types = types;
 2567881754        errorMsg = errMsg;
 2567881755      }
 1756
 01757      public override string ToString() {
 01758        var s = ConstraintName + ":";
 01759        foreach (var t in Types) {
 01760          s += " " + t;
 01761        }
 01762        return s;
 01763      }
 1764
 1765      /// <summary>
 1766      /// Tries to confirm the XConstraint.
 1767      /// If the XConstraint can be confirmed, or at least is plausible enough to have been converted into other type
 1768      /// constraints or more XConstraints, then "true" is returned and the out-parameters "convertedIntoOtherTypeConstr
 1769      /// and "moreXConstraints" are set to true accordingly.
 1770      /// If the XConstraint can be refuted, then an error message will be produced and "true" is returned (to indicate
 1771      /// that this XConstraint has finished serving its purpose).
 1772      /// If there's not enough information to confirm or refute the XConstraint, then "false" is returned.
 1773      /// </summary>
 65196441774      public bool Confirm(Resolver resolver, bool fullstrength, out bool convertedIntoOtherTypeConstraints, out bool mor
 1775        Contract.Requires(resolver != null);
 65196441776        convertedIntoOtherTypeConstraints = false;
 65196441777        moreXConstraints = false;
 65196441778        var t = Types[0].NormalizeExpand();
 110296131779        if (t is TypeProxy) {
 45099691780          switch (ConstraintName) {
 1781            case "Assignable":
 1782            case "Equatable":
 1783            case "EquatableArg":
 1784            case "Indexable":
 1785            case "Innable":
 1786            case "MultiIndexable":
 1787            case "IntOrORDINAL":
 1788              // have a go downstairs
 27965451789              break;
 1790            default:
 17134241791              return false;  // there's not enough information to confirm or refute this XConstraint
 1792          }
 27965451793        }
 1794        bool satisfied;
 48062201795        switch (ConstraintName) {
 45523851796          case "Assignable": {
 45523851797              Contract.Assert(t == t.Normalize());  // it's already been normalized above
 45523851798              var u = Types[1].NormalizeExpand();
 45523851799              if (CheckTypeInferenceVisitor.IsDetermined(t) &&
 45523851800                  (fullstrength
 45523851801                   || !ProxyWithNoSubTypeConstraint(u, resolver)
 45523851802                   || (u is TypeProxy
 45523851803                       && Types[0].NormalizeExpandKeepConstraints() is var t0constrained
 45523851804                       && (t0constrained.IsNonNullRefType || t0constrained.AsSubsetType != null)
 46661221805                       && resolver.HasApplicableNullableRefTypeConstraint(new HashSet<TypeProxy>() { (TypeProxy)u })))) 
 1806                // This is the best case.  We convert Assignable(t, u) to the subtype constraint base(t) :> u.
 1209071807                if (CheckTypeInferenceVisitor.IsDetermined(u) && t.IsSubtypeOf(u, false, true) && t.IsRefType) {
 1808                  // But we also allow cases where the rhs is a proper supertype of the lhs, and let the verifier
 1809                  // determine whether the rhs is provably an instance of the lhs.
 71701810                  resolver.ConstrainAssignable((NonProxyType)u, (NonProxyType)t, errorMsg, out moreXConstraints, fullstr
 1137371811                } else {
 1065671812                  resolver.ConstrainAssignable((NonProxyType)t, u, errorMsg, out moreXConstraints, fullstrength);
 1065671813                }
 1137371814                convertedIntoOtherTypeConstraints = true;
 1137371815                return true;
 44395041816              } else if (u.IsTypeParameter) {
 1817                // we need the constraint base(t) :> u, which for a type parameter t can happen iff t :> u
 8561818                resolver.ConstrainSubtypeRelation(t, u, errorMsg);
 8561819                convertedIntoOtherTypeConstraints = true;
 8561820                return true;
 44432321821              } else if (Type.FromSameHead(t, u, out var tUp, out var uUp)) {
 54401822                resolver.ConstrainAssignableTypeArgs(tUp, tUp.TypeArgs, uUp.TypeArgs, errorMsg, out moreXConstraints);
 54401823                return true;
 44323521824              } else if (fullstrength && t is NonProxyType) {
 1825                // We convert Assignable(t, u) to the subtype constraint base(t) :> u.
 01826                resolver.ConstrainAssignable((NonProxyType)t, u, errorMsg, out moreXConstraints, fullstrength);
 01827                convertedIntoOtherTypeConstraints = true;
 01828                return true;
 44323521829              } else if (fullstrength && u is NonProxyType) {
 1830                // We're willing to change "base(t) :> u" to the stronger constraint "t :> u" for the sake of making pro
 01831                resolver.ConstrainSubtypeRelation(t, u, errorMsg);
 01832                convertedIntoOtherTypeConstraints = true;
 01833                return true;
 1834              }
 1835              // There's not enough information to say anything
 44323521836              return false;
 1837            }
 1838          case "NumericType":
 01839            satisfied = t.IsNumericBased();
 01840            break;
 1841          case "IntegerType":
 38351842            satisfied = t.IsNumericBased(Type.NumericPersuasion.Int);
 38351843            break;
 1844          case "IsBitvector":
 01845            satisfied = t.IsBitVectorType;
 01846            break;
 1847          case "IsRefType":
 01848            satisfied = t.IsRefType;
 01849            break;
 1850          case "IsNullableRefType":
 2241851            satisfied = t.IsRefType && !t.IsNonNullRefType;
 2241852            break;
 1853          case "Orderable_Lt":
 71371854            satisfied = t.IsNumericBased() || t.IsBitVectorType || t.IsBigOrdinalType || t.IsCharType || t is SeqType ||
 71371855            break;
 1856          case "Orderable_Gt":
 87171857            satisfied = t.IsNumericBased() || t.IsBitVectorType || t.IsBigOrdinalType || t.IsCharType || t is SetType ||
 87171858            break;
 01859          case "RankOrderable": {
 01860              var u = Types[1].NormalizeExpand();
 01861              if (u is TypeProxy) {
 01862                return false;  // not enough information
 1863              }
 01864              satisfied = (t.IsIndDatatype || t.IsTypeParameter) && u.IsIndDatatype;
 01865              break;
 1866            }
 1867          case "Plussable":
 13301868            satisfied = t.IsNumericBased() || t.IsBitVectorType || t.IsBigOrdinalType || t.IsCharType || t is SeqType ||
 13301869            break;
 1870          case "Minusable":
 12991871            satisfied = t.IsNumericBased() || t.IsBitVectorType || t.IsBigOrdinalType || t.IsCharType || t is SetType ||
 12991872            break;
 1873          case "Mullable":
 1951874            satisfied = t.IsNumericBased() || t.IsBitVectorType || t is SetType || t is MultiSetType;
 1951875            break;
 1876          case "IntOrORDINAL":
 01877            if (!(t is TypeProxy)) {
 01878              if (TernaryExpr.PrefixEqUsesNat) {
 01879                satisfied = t.IsNumericBased(Type.NumericPersuasion.Int);
 01880              } else {
 01881                satisfied = t.IsNumericBased(Type.NumericPersuasion.Int) || t.IsBigOrdinalType;
 01882              }
 01883            } else if (fullstrength) {
 01884              var proxy = (TypeProxy)t;
 01885              if (TernaryExpr.PrefixEqUsesNat) {
 01886                resolver.AssignProxyAndHandleItsConstraints(proxy, Type.Int);
 01887              } else {
 1888                // let's choose ORDINAL over int
 01889                resolver.AssignProxyAndHandleItsConstraints(proxy, Type.BigOrdinal);
 01890              }
 01891              convertedIntoOtherTypeConstraints = true;
 01892              satisfied = true;
 01893            } else {
 01894              return false;
 1895            }
 01896            break;
 1897          case "NumericOrBitvector":
 161981898            satisfied = t.IsNumericBased() || t.IsBitVectorType;
 161981899            break;
 1900          case "NumericOrBitvectorOrCharOrORDINAL":
 01901            satisfied = t.IsNumericBased() || t.IsBitVectorType || t.IsCharType || t.IsBigOrdinalType;
 01902            break;
 1903          case "IntLikeOrBitvector":
 6131904            satisfied = t.IsNumericBased(Type.NumericPersuasion.Int) || t.IsBitVectorType;
 6131905            break;
 1906          case "BooleanBits":
 251907            satisfied = t.IsBoolType || t.IsBitVectorType;
 251908            break;
 1909          case "Sizeable":
 92201910            satisfied = (t is SetType && ((SetType)t).Finite) || t is MultiSetType || t is SeqType || (t is MapType && (
 92201911            break;
 1912          case "Disjointable":
 401913            satisfied = t is SetType || t is MultiSetType;
 401914            break;
 1915          case "MultiSetConvertible":
 7101916            satisfied = (t is SetType && ((SetType)t).Finite) || t is SeqType;
 14201917            if (satisfied) {
 7101918              Type elementType = ((CollectionType)t).Arg;
 7101919              var u = Types[1];  // note, it's okay if "u" is a TypeProxy
 7101920              var em = new TypeConstraint.ErrorMsgWithBase(errorMsg, "expecting element type {0} (got {1})", u, elementT
 7101921              resolver.ConstrainSubtypeRelation_Equal(elementType, u, em);
 7101922              convertedIntoOtherTypeConstraints = true;
 7101923            }
 7101924            break;
 1925          case "IsCoDatatype":
 01926            satisfied = t.IsCoDatatype;
 01927            break;
 1928          case "Indexable":
 255321929            if (!(t is TypeProxy)) {
 127661930              satisfied = t is SeqType || t is MultiSetType || t is MapType || (t.IsArrayType && t.AsArrayType.Dims == 1
 127661931            } else {
 1932              // t is a proxy, but perhaps it stands for something between "object" and "array<?>".  If so, we can add a
 1933              // that it does have the form "array<?>", since "object" would not be Indexable.
 01934              var proxy = (TypeProxy)t;
 01935              Type join = null;
 01936              if (resolver.JoinOfAllSubtypes(proxy, ref join, new HashSet<TypeProxy>()) && join != null) {
 01937                var headWithProxyArgs = Type.HeadWithProxyArgs(join);
 01938                var tt = headWithProxyArgs.NormalizeExpand();
 01939                satisfied = tt is SeqType || tt is MultiSetType || tt is MapType || (tt.IsArrayType && tt.AsArrayType.Di
 01940                if (satisfied) {
 01941                  resolver.AssignProxyAndHandleItsConstraints(proxy, headWithProxyArgs, true);
 01942                  convertedIntoOtherTypeConstraints = true;
 01943                }
 01944              } else {
 01945                return false;  // we can't determine the answer
 1946              }
 01947            }
 127661948            break;
 1949          case "MultiIndexable":
 14701950            if (!(t is TypeProxy)) {
 7351951              satisfied = t is SeqType || (t.IsArrayType && t.AsArrayType.Dims == 1);
 7351952            } else {
 1953              // t is a proxy, but perhaps it stands for something between "object" and "array<?>".  If so, we can add a
 1954              // that it does have the form "array<?>", since "object" would not be Indexable.
 01955              var proxy = (TypeProxy)t;
 01956              Type join = null;
 01957              if (resolver.JoinOfAllSubtypes(proxy, ref join, new HashSet<TypeProxy>()) && join != null) {
 01958                var headWithProxyArgs = Type.HeadWithProxyArgs(join);
 01959                var tt = headWithProxyArgs.NormalizeExpand();
 01960                satisfied = tt is SeqType || (tt.IsArrayType && tt.AsArrayType.Dims == 1);
 01961                if (satisfied) {
 01962                  resolver.AssignProxyAndHandleItsConstraints(proxy, headWithProxyArgs, true);
 01963                  convertedIntoOtherTypeConstraints = true;
 01964                }
 01965              } else {
 01966                return false;  // we can't determine the answer
 1967              }
 01968            }
 7351969            break;
 42671970          case "Innable": {
 42671971              var elementType = FindCollectionType(resolver.Options, t, true, new HashSet<TypeProxy>()) ?? FindCollectio
 85341972              if (elementType != null) {
 42671973                var u = Types[1];  // note, it's okay if "u" is a TypeProxy
 42671974                resolver.AddXConstraint(this.tok, "Equatable", elementType, u, new TypeConstraint.ErrorMsgWithBase(error
 42671975                moreXConstraints = true;
 42671976                return true;
 1977              }
 01978              if (t is TypeProxy) {
 01979                return false;  // not enough information to do anything
 1980              }
 01981              satisfied = false;
 01982              break;
 1983            }
 20891984          case "SeqUpdatable": {
 20891985              var xcWithExprs = (XConstraintWithExprs)this;
 20891986              var index = xcWithExprs.Exprs[0];
 20891987              var value = xcWithExprs.Exprs[1];
 28941988              if (t is SeqType) {
 8051989                var s = (SeqType)t;
 8051990                resolver.ConstrainToIntegerType(index, true, "sequence update requires integer- or bitvector-based index
 8051991                resolver.ConstrainSubtypeRelation(s.Arg, value.Type, value, "sequence update requires the value to have 
 33731992              } else if (t is MapType) {
 12841993                var s = (MapType)t;
 25681994                if (s.Finite) {
 12841995                  resolver.ConstrainSubtypeRelation(s.Domain, index.Type, index, "map update requires domain element to 
 12841996                  resolver.ConstrainSubtypeRelation(s.Range, value.Type, value, "map update requires the value to have t
 12841997                } else {
 01998                  resolver.ConstrainSubtypeRelation(s.Domain, index.Type, index, "imap update requires domain element to
 01999                  resolver.ConstrainSubtypeRelation(s.Range, value.Type, value, "imap update requires the value to have 
 02000                }
 12842001              } else if (t is MultiSetType) {
 02002                var s = (MultiSetType)t;
 02003                resolver.ConstrainSubtypeRelation(s.Arg, index.Type, index, "multiset update requires domain element to 
 02004                resolver.ConstrainToIntegerType(value, false, "multiset update requires integer-based numeric value (got
 02005              } else {
 02006                satisfied = false;
 02007                break;
 2008              }
 20892009              convertedIntoOtherTypeConstraints = true;
 20892010              return true;
 2011            }
 2012          case "ContainerIndex":
 2013            // The semantics of this XConstraint is that *if* the head is seq/array/map/multiset, then its element/domai
 2014            Type indexType;
 244902015            if (t is SeqType || t.IsArrayType) {
 102542016              resolver.ConstrainToIntegerType(errorMsg.Tok, Types[1], true, errorMsg);
 102542017              convertedIntoOtherTypeConstraints = true;
 102542018              return true;
 79642019            } else if (t is MapType) {
 39822020              indexType = ((MapType)t).Domain;
 39822021            } else if (t is MultiSetType) {
 02022              indexType = ((MultiSetType)t).Arg;
 02023            } else {
 2024              // some other head symbol; that's cool
 02025              return true;
 2026            }
 2027            // note, it's okay if "Types[1]" is a TypeProxy
 39822028            resolver.ConstrainSubtypeRelation(indexType, Types[1], errorMsg);  // use the same error message
 39822029            convertedIntoOtherTypeConstraints = true;
 39822030            return true;
 2031          case "ContainerResult":
 2032            // The semantics of this XConstraint is that *if* the head is seq/array/map/multiset, then the type of a sel
 2033            Type resultType;
 190102034            if (t is SeqType) {
 55092035              resultType = ((SeqType)t).Arg;
 175112036            } else if (t.IsArrayType) {
 40102037              resultType = UserDefinedType.ArrayElementType(t);
 119742038            } else if (t is MapType) {
 39822039              resultType = ((MapType)t).Range;
 39822040            } else if (t is MultiSetType) {
 02041              resultType = resolver.builtIns.Nat();
 02042            } else {
 2043              // some other head symbol; that's cool
 02044              return true;
 2045            }
 2046            // note, it's okay if "Types[1]" is a TypeProxy
 135012047            resolver.ConstrainSubtypeRelation(Types[1], resultType, errorMsg);
 135012048            convertedIntoOtherTypeConstraints = true;
 135012049            return true;
 475722050          case "Equatable": {
 475722051              t = Types[0].NormalizeExpandKeepConstraints();
 475722052              var u = Types[1].NormalizeExpandKeepConstraints();
 483122053              if (object.ReferenceEquals(t, u)) {
 7402054                return true;
 2055              }
 639222056              if (t is TypeProxy && u is TypeProxy) {
 170902057                return false;  // not enough information to do anything sensible
 409992058              } else if (t is TypeProxy || u is TypeProxy) {
 2059                TypeProxy proxy;
 2060                Type other;
 144872061                if (t is TypeProxy) {
 32302062                  proxy = (TypeProxy)t;
 32302063                  other = u;
 112572064                } else {
 80272065                  proxy = (TypeProxy)u;
 80272066                  other = t;
 80272067                }
 188462068                if (other.IsNumericBased() || other.IsBitVectorType || other.IsBigOrdinalType) {
 75892069                  resolver.ConstrainSubtypeRelation(other.NormalizeExpand(), proxy, errorMsg, true);
 75892070                  convertedIntoOtherTypeConstraints = true;
 75892071                  return true;
 39022072                } else if (fullstrength) {
 2073                  // the following is rather aggressive
 2342074                  if (Resolver.TypeConstraintsIncludeProxy(other, proxy)) {
 02075                    return false;
 2342076                  } else {
 4582077                    if (other.IsRefType && resolver.HasApplicableNullableRefTypeConstraint_SubDirection(proxy)) {
 2242078                      other = other.NormalizeExpand();  // shave off all constraints
 2242079                    }
 2342080                    satisfied = resolver.AssignProxyAndHandleItsConstraints(proxy, other, true);
 2342081                    convertedIntoOtherTypeConstraints = true;
 2342082                    break;
 2083                  }
 34342084                } else {
 34342085                  return false;  // not enough information
 2086                }
 2087              }
 2088
 184852089              satisfied = Type.FromSameHead_Subtype(t, u, out var a, out var b);
 369702090              if (satisfied) {
 184852091                Contract.Assert(a.TypeArgs.Count == b.TypeArgs.Count);
 184852092                var cl = a is UserDefinedType ? ((UserDefinedType)a).ResolvedClass : null;
 664362093                for (int i = 0; i < a.TypeArgs.Count; i++) {
 98222094                  resolver.AllXConstraints.Add(new XConstraint_EquatableArg(tok,
 98222095                    a.TypeArgs[i], b.TypeArgs[i],
 98222096                    a is CollectionType || (cl != null && cl.TypeArgs[i].Variance != TypeParameter.TPVariance.Non),
 98222097                    a.IsRefType,
 98222098                    errorMsg));
 98222099                  moreXConstraints = true;
 98222100                }
 184852101              }
 184852102              break;
 2103            }
 1091262104          case "EquatableArg": {
 1091262105              t = Types[0].NormalizeExpandKeepConstraints();
 1091262106              var u = Types[1].NormalizeExpandKeepConstraints();
 1091262107              var moreExactThis = (XConstraint_EquatableArg)this;
 1168062108              if (t is TypeProxy && u is TypeProxy) {
 76802109                return false;  // not enough information to do anything sensible
 1930402110              } else if (t is TypeProxy || u is TypeProxy) {
 2111                TypeProxy proxy;
 2112                Type other;
 915942113                if (t is TypeProxy) {
 02114                  proxy = (TypeProxy)t;
 02115                  other = u;
 915942116                } else {
 915942117                  proxy = (TypeProxy)u;
 915942118                  other = t;
 915942119                }
 937142120                if (other.IsNumericBased() || other.IsBitVectorType || other.IsBigOrdinalType) {
 21202121                  resolver.ConstrainSubtypeRelation(other.NormalizeExpand(), proxy, errorMsg, true);
 21202122                  convertedIntoOtherTypeConstraints = true;
 21202123                  return true;
 898922124                } else if (fullstrength) {
 2125                  // the following is rather aggressive
 4182126                  if (Resolver.TypeConstraintsIncludeProxy(other, proxy)) {
 02127                    return false;
 4182128                  } else {
 4182129                    if (other.IsRefType && resolver.HasApplicableNullableRefTypeConstraint_SubDirection(proxy)) {
 02130                      other = other.NormalizeExpand();  // shave off all constraints
 02131                    }
 4182132                    satisfied = resolver.AssignProxyAndHandleItsConstraints(proxy, other, true);
 4182133                    convertedIntoOtherTypeConstraints = true;
 4182134                    break;
 2135                  }
 890562136                } else {
 890562137                  return false;  // not enough information
 2138                }
 2139              }
 98522140              if (moreExactThis.TreatTypeParamAsWild && (t.IsTypeParameter || u.IsTypeParameter || t.IsAbstractType || u
 02141                return true;
 105812142              } else if (!moreExactThis.AllowSuperSub) {
 7292143                resolver.ConstrainSubtypeRelation_Equal(t, u, errorMsg);
 7292144                convertedIntoOtherTypeConstraints = true;
 7292145                return true;
 2146              }
 2147
 2148              // okay if t<:u or u<:t (this makes type inference more manageable, though it is more liberal than one mig
 91232149              satisfied = Type.FromSameHead_Subtype(t, u, out var a, out var b);
 182462150              if (satisfied) {
 91232151                Contract.Assert(a.TypeArgs.Count == b.TypeArgs.Count);
 91232152                var cl = a is UserDefinedType ? ((UserDefinedType)a).ResolvedClass : null;
 259502153                for (int i = 0; i < a.TypeArgs.Count; i++) {
 25682154                  resolver.AllXConstraints.Add(new XConstraint_EquatableArg(tok,
 25682155                    a.TypeArgs[i], b.TypeArgs[i],
 25682156                    a is CollectionType || (cl != null && cl.TypeArgs[i].Variance != TypeParameter.TPVariance.Non),
 25682157                    false,
 25682158                    errorMsg));
 25682159                  moreXConstraints = true;
 25682160                }
 91232161              }
 91232162              break;
 2163            }
 02164          case "Freshable": {
 02165              var collType = t.AsCollectionType;
 02166              if (collType is SetType || collType is SeqType) {
 02167                t = collType.Arg.NormalizeExpand();
 02168              }
 02169              if (t is TypeProxy) {
 02170                return false;  // there is not enough information
 2171              }
 02172              satisfied = t.IsRefType;
 02173              break;
 2174            }
 02175          case "ModifiesFrame": {
 02176              var u = Types[1].NormalizeExpand();  // eventual ref type
 02177              var collType = t is MapType ? null : t.AsCollectionType;
 02178              if (collType != null) {
 02179                t = collType.Arg.NormalizeExpand();
 02180              }
 02181              if (t is TypeProxy) {
 02182                if (collType != null) {
 2183                  // we know enough to convert into a subtyping constraint
 02184                  resolver.AddXConstraint(Token.NoToken/*bogus, but it seems this token would be used only when integers
 02185                  moreXConstraints = true;
 02186                  resolver.ConstrainSubtypeRelation_Equal(u, t, errorMsg);
 02187                  moreXConstraints = true;
 02188                  convertedIntoOtherTypeConstraints = true;
 02189                  return true;
 02190                } else {
 02191                  return false;  // there is not enough information
 2192                }
 2193              }
 02194              if (t.IsRefType) {
 02195                resolver.ConstrainSubtypeRelation_Equal(u, t, errorMsg);
 02196                convertedIntoOtherTypeConstraints = true;
 02197                return true;
 2198              }
 02199              satisfied = false;
 02200              break;
 2201            }
 02202          case "ReadsFrame": {
 02203              var u = Types[1].NormalizeExpand();  // eventual ref type
 02204              var arrTy = t.AsArrowType;
 02205              if (arrTy != null) {
 02206                t = arrTy.Result.NormalizeExpand();
 02207              }
 02208              var collType = t is MapType ? null : t.AsCollectionType;
 02209              if (collType != null) {
 02210                t = collType.Arg.NormalizeExpand();
 02211              }
 02212              if (t is TypeProxy) {
 02213                if (collType != null) {
 2214                  // we know enough to convert into a subtyping constraint
 02215                  resolver.AddXConstraint(Token.NoToken/*bogus, but it seems this token would be used only when integers
 02216                  resolver.ConstrainSubtypeRelation_Equal(u, t, errorMsg);
 02217                  moreXConstraints = true;
 02218                  convertedIntoOtherTypeConstraints = true;
 02219                  return true;
 02220                } else {
 02221                  return false;  // there is not enough information
 2222                }
 2223              }
 02224              if (t.IsRefType && (arrTy == null || collType != null)) {
 02225                resolver.ConstrainSubtypeRelation_Equal(u, t, errorMsg);
 02226                convertedIntoOtherTypeConstraints = true;
 02227                return true;
 2228              }
 02229              satisfied = false;
 02230              break;
 2231            }
 2232          default:
 02233            Contract.Assume(false);  // unknown XConstraint
 02234            return false;  // to please the compiler
 2235        }
 913042236        if (!satisfied) {
 02237          errorMsg.FlagAsError(resolver);
 02238        }
 913042239        return true;  // the XConstraint has served its purpose
 65196442240      }
 2241
 17778552242      public bool ProxyWithNoSubTypeConstraint(Type u, Resolver resolver) {
 2243        Contract.Requires(u != null);
 2244        Contract.Requires(resolver != null);
 17778552245        var proxy = u as TypeProxy;
 34441282246        if (proxy != null) {
 16674782247          if (proxy.SubtypeConstraints.Any()) {
 12052248            return false;
 2249          }
 5061829092250          foreach (var xc in resolver.AllXConstraints) {
 1670638352251            if (xc.ConstraintName == "Assignable" && xc.Types[0] == proxy) {
 9502252              return false;
 2253            }
 1670619352254          }
 16641182255          return true;
 2256        }
 1115822257        return false;
 17778552258      }
 2259
 02260      internal bool CouldBeAnything() {
 02261        return Types.All(t => t.NormalizeExpand() is TypeProxy);
 02262      }
 2263
 2264      /// <summary>
 2265      /// If "t" or any type among its transitive sub/super-types (depending on "towardsSub")
 2266      /// is a collection type, then returns the element/domain type of that collection.
 2267      /// Otherwise, returns null.
 2268      /// </summary>
 42672269      Type FindCollectionType(DafnyOptions options, Type t, bool towardsSub, ISet<TypeProxy> visited) {
 2270        Contract.Requires(t != null);
 2271        Contract.Requires(visited != null);
 42672272        t = t.NormalizeExpand();
 42672273        if (options.Get(CommonOptionBag.TypeInferenceDebug)) {
 02274          options.OutputWriter.WriteLine("DEBUG: FindCollectionType({0}, {1})", t, towardsSub ? "sub" : "super");
 02275        }
 85342276        if (t is CollectionType) {
 42672277          if (options.Get(CommonOptionBag.TypeInferenceDebug)) {
 02278            options.OutputWriter.WriteLine("DEBUG: FindCollectionType({0}) = {1}", t, ((CollectionType)t).Arg);
 02279          }
 42672280          return ((CollectionType)t).Arg;
 2281        }
 02282        var proxy = t as TypeProxy;
 02283        if (proxy == null || visited.Contains(proxy)) {
 02284          return null;
 2285        }
 02286        visited.Add(proxy);
 02287        foreach (var sub in towardsSub ? proxy.Subtypes : proxy.Supertypes) {
 02288          var e = FindCollectionType(options, sub, towardsSub, visited);
 02289          if (e != null) {
 02290            return e;
 2291          }
 02292        }
 02293        return null;
 42672294      }
 2295    }
 2296
 2297    public class XConstraintWithExprs : XConstraint {
 2298      public readonly Expression[] Exprs;
 2299      public XConstraintWithExprs(IToken tok, string constraintName, Type[] types, Expression[] exprs, TypeConstraint.Er
 41782300        : base(tok, constraintName, types, errMsg) {
 2301        Contract.Requires(tok != null);
 2302        Contract.Requires(constraintName != null);
 2303        Contract.Requires(types != null);
 2304        Contract.Requires(exprs != null);
 2305        Contract.Requires(errMsg != null);
 20892306        this.Exprs = exprs;
 20892307      }
 2308    }
 2309
 2310    public class XConstraint_EquatableArg : XConstraint {
 2311      public bool AllowSuperSub;
 2312      public bool TreatTypeParamAsWild;
 2313      public XConstraint_EquatableArg(IToken tok, Type a, Type b, bool allowSuperSub, bool treatTypeParamAsWild, TypeCon
 247802314        : base(tok, "EquatableArg", new Type[] { a, b }, errMsg) {
 2315        Contract.Requires(tok != null);
 2316        Contract.Requires(a != null);
 2317        Contract.Requires(b != null);
 2318        Contract.Requires(errMsg != null);
 123902319        AllowSuperSub = allowSuperSub;
 123902320        TreatTypeParamAsWild = treatTypeParamAsWild;
 123902321      }
 2322    }
 2323
 2324    /// <summary>
 2325    /// Solves or simplifies as many type constraints as possible.
 2326    /// If "allowDecisions" is "false", then no decisions, only determined inferences, are made; this mode is
 2327    /// appropriate for the partial solving that's done before a member lookup.
 2328    /// </summary>
 276442329    public void PartiallySolveTypeConstraints(bool allowDecisions) {
 276442330      int state = 0;
 3635582331      while (true) {
 1966352332        if (2 <= state && !allowDecisions) {
 2333          // time to say goodnight to Napoli
 148562334          return;
 1797112335        } else if (AllTypeConstraints.Count == 0 && AllXConstraints.Count == 0) {
 2336          // we're done
 127882337          return;
 2338        }
 2339
 1541352340        var anyNewConstraints = false;
 1541352341        var fullStrength = false;
 2342        // Process subtyping constraints
 1541352343        PrintTypeConstraintState(220 + 2 * state);
 1541352344        switch (state) {
 745122345          case 0: {
 745122346              var allTypeConstraints = AllTypeConstraints;
 745122347              AllTypeConstraints = new List<TypeConstraint>();
 745122348              var processed = new HashSet<TypeConstraint>();
 635844272349              foreach (var c in allTypeConstraints) {
 211202972350                ProcessOneSubtypingConstraintAndItsSubs(c, processed, fullStrength, ref anyNewConstraints);
 211202972351              }
 2352
 745122353              allTypeConstraints = new List<TypeConstraint>(AllTypeConstraints);  // copy the list
 619836392354              foreach (var c in allTypeConstraints) {
 205867012355                var super = c.Super.NormalizeExpand() as TypeProxy;
 205871512356                if (AssignKnownEnd(super, true, fullStrength)) {
 4502357                  anyNewConstraints = true;
 205867012358                } else if (super != null && fullStrength && AssignKnownEndsFullstrength(super)) {  // KRML: is this used
 02359                  anyNewConstraints = true;
 02360                }
 205867012361              }
 745122362            }
 745122363            break;
 2364
 539532365          case 1: {
 2366              // Process XConstraints
 2367              // confirm as many XConstraints as possible, setting "anyNewConstraints" to "true" if the confirmation
 2368              // of an XConstraint gives rise to new constraints to be handled in the loop above
 2369              bool generatedMoreXConstraints;
 770762370              do {
 770762371                generatedMoreXConstraints = false;
 770762372                var allXConstraints = AllXConstraints;
 770762373                AllXConstraints = new List<XConstraint>();
 197882042374                foreach (var xc in allXConstraints) {
 67749482375                  if (xc.Confirm(this, fullStrength, out var convertedIntoOtherTypeConstraints, out var moreXConstraints
 4115232376                    if (convertedIntoOtherTypeConstraints) {
 1555672377                      anyNewConstraints = true;
 2559562378                    } else {
 1003892379                      generatedMoreXConstraints = true;
 1003892380                    }
 2718102381                    if (moreXConstraints) {
 158542382                      generatedMoreXConstraints = true;
 158542383                    }
 65189922384                  } else {
 62630362385                    AllXConstraints.Add(xc);
 62630362386                  }
 65189922387                }
 1541522388              } while (generatedMoreXConstraints);
 539532389            }
 539532390            break;
 2391
 139942392          case 2: {
 15463572393              var assignables = AllXConstraints.Where(xc => xc.ConstraintName == "Assignable").ToList();
 139942394              var postponeForNow = new HashSet<TypeProxy>();
 167687012395              foreach (var constraint in AllTypeConstraints) {
 55755732396                var lhs = constraint.Super.NormalizeExpandKeepConstraints() as NonProxyType;
 68813782397                if (lhs != null) {
 42667952398                  foreach (var ta in lhs.TypeArgs) {
 1164602399                    AddAllProxies(ta, postponeForNow);
 1164602400                  }
 13058052401                }
 55755732402              }
 167687012403              foreach (var constraint in AllTypeConstraints) {
 55755732404                var lhs = constraint.Super.Normalize() as TypeProxy;
 70299232405                if (lhs != null && !postponeForNow.Contains(lhs)) {
 1851273952406                  var rhss = assignables.Where(xc => xc.Types[0].Normalize() == lhs).Select(xc => xc.Types[1]).ToList();
 14569152407                  if (ProcessAssignable(lhs, rhss)) {
 25652408                    anyNewConstraints = true;  // next time around the big loop, start with state 0 again
 25652409                  }
 14543502410                }
 55755732411              }
 12416242412              foreach (var assignable in assignables) {
 4028472413                var lhs = assignable.Types[0].Normalize() as TypeProxy;
 6025462414                if (lhs != null && !postponeForNow.Contains(lhs)) {
 263293062415                  var rhss = assignables.Where(xc => xc.Types[0].Normalize() == lhs).Select(xc => xc.Types[1]).ToList();
 2085982416                  if (ProcessAssignable(lhs, rhss)) {
 88992417                    anyNewConstraints = true;  // next time around the big loop, start with state 0 again
 2418                                               // process only one Assignable constraint in this way
 88992419                    break;
 2420                  }
 1908002421                }
 3939482422              }
 139942423            }
 139942424            break;
 2425
 2426          case 3:
 50052427            anyNewConstraints = ConvertAssignableToSubtypeConstraints(null);
 50052428            break;
 2429
 49302430          case 4: {
 49302431              var allTC = AllTypeConstraints;
 49302432              AllTypeConstraints = new List<TypeConstraint>();
 49302433              var proxyProcessed = new HashSet<TypeProxy>();
 7442282434              foreach (var c in allTC) {
 2431462435                ProcessFullStrength_SubDirection(c.Super, proxyProcessed, ref anyNewConstraints);
 2431462436              }
 2288102437              foreach (var xc in AllXConstraints) {
 1109242438                if (xc.ConstraintName == "Assignable") {
 395842439                  ProcessFullStrength_SubDirection(xc.Types[0], proxyProcessed, ref anyNewConstraints);
 395842440                }
 713402441              }
 98152442              if (!anyNewConstraints) {
 2443                // only do super-direction if sub-direction had no effect
 48852444                proxyProcessed = new HashSet<TypeProxy>();
 6613982445                foreach (var c in allTC) {
 2155812446                  ProcessFullStrength_SuperDirection(c.Sub, proxyProcessed, ref anyNewConstraints);
 2155812447                }
 2079302448                foreach (var xc in AllXConstraints) {
 1004042449                  if (xc.ConstraintName == "Assignable") {
 359792450                    ProcessFullStrength_SuperDirection(xc.Types[1], proxyProcessed, ref anyNewConstraints);
 359792451                  }
 644252452                }
 48852453              }
 49302454              AllTypeConstraints.AddRange(allTC);
 49302455            }
 49302456            break;
 2457
 13382458          case 5: {
 2459              // Process default numeric types
 13382460              var allTypeConstraints = AllTypeConstraints;
 13382461              AllTypeConstraints = new List<TypeConstraint>();
 767942462              foreach (var c in allTypeConstraints) {
 458052463                if (c.Super is ArtificialType) {
 215452464                  var proxy = c.Sub.NormalizeExpand() as TypeProxy;
 319002465                  if (proxy != null) {
 103552466                    AssignProxyAndHandleItsConstraints(proxy, c.Super is IntVarietiesSupertype ? (Type)Type.Int : Type.R
 103552467                    anyNewConstraints = true;
 103552468                    continue;
 2469                  }
 111902470                }
 139052471                AllTypeConstraints.Add(c);
 139052472              }
 13382473            }
 13382474            break;
 2475
 3932476          case 6: {
 3932477              fullStrength = true;
 2478              bool generatedMoreXConstraints;
 3932479              do {
 3932480                generatedMoreXConstraints = false;
 3932481                var allXConstraints = AllXConstraints;
 3932482                AllXConstraints = new List<XConstraint>();
 38072483                foreach (var xc in allXConstraints) {
 15282484                  if ((xc.ConstraintName == "Equatable" || xc.ConstraintName == "EquatableArg") && xc.Confirm(this, full
 13042485                    if (convertedIntoOtherTypeConstraints) {
 6522486                      anyNewConstraints = true;
 6522487                    } else {
 02488                      generatedMoreXConstraints = true;
 02489                    }
 6522490                    if (moreXConstraints) {
 02491                      generatedMoreXConstraints = true;
 02492                    }
 8762493                  } else {
 2242494                    AllXConstraints.Add(xc);
 2242495                  }
 8762496                }
 7862497              } while (generatedMoreXConstraints);
 3932498            }
 3932499            break;
 2500
 52501          case 7: {
 2502              // Process default reference types
 52503              var allXConstraints = AllXConstraints;
 52504              AllXConstraints = new List<XConstraint>();
 152505              foreach (var xc in allXConstraints) {
 02506                if (xc.ConstraintName == "IsRefType" || xc.ConstraintName == "IsNullableRefType") {
 02507                  var proxy = xc.Types[0].Normalize() as TypeProxy;  // before we started processing default types, this
 02508                  if (proxy != null) {
 02509                    AssignProxyAndHandleItsConstraints(proxy, builtIns.ObjectQ());
 02510                    anyNewConstraints = true;
 02511                    continue;
 2512                  }
 02513                }
 02514                AllXConstraints.Add(xc);
 02515              }
 52516            }
 52517            break;
 2518
 102519          case 8: fullStrength = true; goto case 0;
 102520          case 9: fullStrength = true; goto case 1;
 2521
 52522          case 10: {
 2523              // Finally, collapse constraints involving only proxies, which will have the effect of trading some type e
 2524              // messages for type-underspecification messages.
 52525              var allTypeConstraints = AllTypeConstraints;
 52526              AllTypeConstraints = new List<TypeConstraint>();
 602527              foreach (var c in allTypeConstraints) {
 152528                var super = c.Super.NormalizeExpand();
 152529                var sub = c.Sub.NormalizeExpand();
 202530                if (super == sub) {
 52531                  continue;
 202532                } else if (super is TypeProxy && sub is TypeProxy) {
 102533                  var proxy = (TypeProxy)super;
 102534                  if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 02535                    Options.OutputWriter.WriteLine("DEBUG: (merge in PartiallySolve) assigning proxy {0}.T := {1}", prox
 02536                  }
 102537                  proxy.T = sub;
 102538                  anyNewConstraints = true;  // signal a change in the constraints
 102539                  continue;
 2540                }
 02541                AllTypeConstraints.Add(c);
 02542              }
 52543            }
 52544            break;
 2545
 02546          case 11: {
 2547              // Last resort decisions. Sometimes get here even with some 'obvious'
 2548              // inferences. Before this case was added, the type inference returned with
 2549              // failure, so this is a conservative addition, and could be made more
 2550              // capable.
 02551              if (!allowDecisions) {
 02552                break;
 2553              }
 2554
 02555              foreach (var c in AllXConstraints) {
 02556                if (c.ConstraintName == "EquatableArg") {
 02557                  ConstrainSubtypeRelation_Equal(c.Types[0], c.Types[1], c.errorMsg);
 02558                  anyNewConstraints = true;
 02559                  AllXConstraints.Remove(c);
 02560                  break;
 2561                }
 02562              }
 02563              if (anyNewConstraints) {
 02564                break;
 2565              }
 2566
 02567              TypeConstraint.ErrorMsg oneSuperErrorMsg = null;
 02568              TypeConstraint.ErrorMsg oneSubErrorMsg = null;
 02569              var ss = new HashSet<Type>();
 02570              foreach (var c in AllTypeConstraints) {
 02571                var super = c.Super.NormalizeExpand();
 02572                var sub = c.Sub.NormalizeExpand();
 02573                if (super is TypeProxy && !ss.Contains(super)) {
 02574                  ss.Add(super);
 02575                }
 02576                if (sub is TypeProxy && !ss.Contains(sub)) {
 02577                  ss.Add(sub);
 02578                }
 02579              }
 2580
 02581              foreach (var t in ss) {
 02582                var lowers = new HashSet<Type>();
 02583                var uppers = new HashSet<Type>();
 02584                foreach (var c in AllTypeConstraints) {
 02585                  var super = c.Super.NormalizeExpand();
 02586                  var sub = c.Sub.NormalizeExpand();
 02587                  if (t.Equals(super)) {
 02588                    lowers.Add(sub);
 02589                    oneSubErrorMsg = c.ErrMsg;
 02590                  }
 02591                  if (t.Equals(sub)) {
 02592                    uppers.Add(super);
 02593                    oneSuperErrorMsg = c.ErrMsg;
 02594                  }
 02595                }
 2596
 02597                bool done = false;
 02598                foreach (var tl in lowers) {
 02599                  foreach (var tu in uppers) {
 02600                    if (tl.Equals(tu)) {
 02601                      if (!ContainsAsTypeParameter(tu, t)) {
 02602                        var errorMsg = new TypeConstraint.ErrorMsgWithBase(AllTypeConstraints[0].ErrMsg,
 02603                          "Decision: {0} is decided to be {1} because the latter is both the upper and lower bound to th
 02604                          t, tu);
 02605                        ConstrainSubtypeRelation_Equal(t, tu, errorMsg);
 2606                        // The above changes t so that it is a proxy with an assigned type
 02607                        anyNewConstraints = true;
 02608                        done = true;
 02609                        break;
 2610                      }
 02611                    }
 02612                  }
 02613                  if (done) {
 02614                    break;
 2615                  }
 02616                }
 02617              }
 02618              if (anyNewConstraints) {
 02619                break;
 2620              }
 2621
 02622              foreach (var t in ss) {
 02623                var lowers = new HashSet<Type>();
 02624                var uppers = new HashSet<Type>();
 02625                foreach (var c in AllTypeConstraints) {
 02626                  var super = c.Super.NormalizeExpand();
 02627                  var sub = c.Sub.NormalizeExpand();
 02628                  if (t.Equals(super)) {
 02629                    lowers.Add(sub);
 02630                  }
 2631
 02632                  if (t.Equals(sub)) {
 02633                    uppers.Add(super);
 02634                  }
 02635                }
 2636
 02637                if (uppers.Count == 0) {
 02638                  if (lowers.Count == 1) {
 02639                    var em = lowers.GetEnumerator();
 02640                    em.MoveNext();
 02641                    if (!ContainsAsTypeParameter(em.Current, t)) {
 02642                      var errorMsg = new TypeConstraint.ErrorMsgWithBase(oneSubErrorMsg,
 02643                        "Decision: {0} is decided to be {1} because the latter is a lower bound to the proxy and there i
 02644                        t, em.Current);
 02645                      ConstrainSubtypeRelation_Equal(t, em.Current, errorMsg);
 02646                      anyNewConstraints = true;
 02647                      break;
 2648                    }
 02649                  }
 02650                }
 02651                if (lowers.Count == 0) {
 02652                  if (uppers.Count == 1) {
 02653                    var em = uppers.GetEnumerator();
 02654                    em.MoveNext();
 02655                    if (!ContainsAsTypeParameter(em.Current, t)) {
 02656                      var errorMsg = new TypeConstraint.ErrorMsgWithBase(oneSuperErrorMsg,
 02657                        "Decision: {0} is decided to be {1} because the latter is an upper bound to the proxy and there 
 02658                        t, em.Current);
 02659                      ConstrainSubtypeRelation_Equal(t, em.Current, errorMsg);
 02660                      anyNewConstraints = true;
 02661                      break;
 2662                    }
 02663                  }
 02664                }
 02665              }
 2666
 02667              break;
 2668            }
 2669
 2670          case 12:
 2671            // we're so out of here
 02672            return;
 2673        }
 2111532674        if (anyNewConstraints) {
 570182675          state = 0;
 1541352676        } else {
 971172677          state++;
 971172678        }
 1541352679      }
 276442680    }
 2681
 14702682    TypeProxy NewIntegerBasedProxy(IToken tok) {
 2683      Contract.Requires(tok != null);
 14702684      var proxy = new InferredTypeProxy();
 14702685      ConstrainSubtypeRelation(new IntVarietiesSupertype(), proxy, tok, "integer literal used as if it had type {0}", pr
 14702686      return proxy;
 14702687    }
 2688
 02689    private bool ContainsAsTypeParameter(Type t, Type u) {
 02690      if (t.Equals(u)) {
 02691        return true;
 2692      }
 2693
 02694      if (t is UserDefinedType udt) {
 02695        foreach (var tp in udt.TypeArgs) {
 02696          if (ContainsAsTypeParameter(tp, u)) {
 02697            return true;
 2698          }
 02699        }
 02700      }
 02701      if (t is CollectionType st) {
 02702        foreach (var tp in st.TypeArgs) {
 02703          if (ContainsAsTypeParameter(tp, u)) {
 02704            return true;
 2705          }
 02706        }
 02707      }
 02708      return false;
 02709    }
 2710
 1167502711    private void AddAllProxies(Type type, HashSet<TypeProxy> proxies) {
 2712      Contract.Requires(type != null);
 2713      Contract.Requires(proxies != null);
 1167502714      var proxy = type as TypeProxy;
 1336902715      if (proxy != null) {
 169402716        proxies.Add(proxy);
 1167502717      } else {
 3003002718        foreach (var ta in type.TypeArgs) {
 2902719          AddAllProxies(ta, proxies);
 2902720        }
 998102721      }
 1167502722    }
 2723
 2724    /// <summary>
 2725    /// Set "lhs" to the join of "rhss" and "lhs.Subtypes, if possible.
 2726    /// Returns "true' if something was done, or "false" otherwise.
 2727    /// </summary>
 16540492728    private bool ProcessAssignable(TypeProxy lhs, List<Type> rhss) {
 2729      Contract.Requires(lhs != null && lhs.T == null);
 2730      Contract.Requires(rhss != null);
 16540492731      if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 02732        Console.Write("DEBUG: ProcessAssignable: {0} with rhss:", lhs);
 02733        foreach (var rhs in rhss) {
 02734          Options.OutputWriter.Write(" {0}", rhs);
 02735        }
 02736        Options.OutputWriter.Write(" subtypes:");
 02737        foreach (var sub in lhs.SubtypesKeepConstraints) {
 02738          Options.OutputWriter.Write(" {0}", sub);
 02739        }
 02740        Options.OutputWriter.WriteLine();
 02741      }
 16540492742      Type join = null;
 54846042743      foreach (var rhs in rhss) {
 6090742744        if (rhs is TypeProxy) { return false; }
 498892745        join = join == null ? rhs : Type.Join(join, rhs, builtIns);
 498892746      }
 73098822747      foreach (var sub in lhs.SubtypesKeepConstraints) {
 43421802748        if (sub is TypeProxy) { return false; }
 52002749        join = join == null ? sub : Type.Join(join, sub, builtIns);
 52002750      }
 325242751      if (join == null) {
 105302752        return false;
 114642753      } else if (Reaches(join, lhs, 1, new HashSet<TypeProxy>())) {
 2754        // would cause a cycle, so don't do it
 02755        return false;
 114642756      } else {
 114642757        if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 02758          Options.OutputWriter.WriteLine("DEBUG: ProcessAssignable: assigning proxy {0}.T := {1}", lhs, join);
 02759        }
 114642760        lhs.T = join;
 114642761        return true;
 2762      }
 16540492763    }
 2764
 2765    /// <summary>
 2766    /// Convert each Assignable(A, B) constraint into a subtyping constraint A :> B,
 2767    /// provided that:
 2768    ///  - B is a non-proxy, and
 2769    ///  - either "proxySpecialization" is null or some proxy in "proxySpecializations" prominently appears in A.
 2770    /// </summary>
 119472771    bool ConvertAssignableToSubtypeConstraints(ISet<TypeProxy>/*?*/ proxySpecializations) {
 119472772      var anyNewConstraints = false;
 2773      // If (the head of) the RHS of an Assignable is known, convert the XConstraint into a subtyping constraint
 119472774      var allX = AllXConstraints;
 119472775      AllXConstraints = new List<XConstraint>();
 12835352776      foreach (var xc in allX) {
 5235582777        if (xc.ConstraintName == "Assignable" && xc.Types[1].Normalize() is NonProxyType) {
 1076602778          var t0 = xc.Types[0].NormalizeExpand();
 1076602779          if (proxySpecializations == null
 1076602780            || proxySpecializations.Contains(t0)
 1078402781            || t0.TypeArgs.Exists(ta => proxySpecializations.Contains(ta))) {
 1802782            ConstrainSubtypeRelation(t0, xc.Types[1], xc.errorMsg, true);
 1802783            anyNewConstraints = true;
 1802784            continue;
 2785          }
 1074802786        }
 4157182787        AllXConstraints.Add(xc);
 4157182788      }
 119472789      return anyNewConstraints;
 119472790    }
 2791
 69422792    bool TightenUpEquatable(ISet<TypeProxy> proxiesOfInterest) {
 2793      Contract.Requires(proxiesOfInterest != null);
 69422794      var anyNewConstraints = false;
 69422795      var allX = AllXConstraints;
 69422796      AllXConstraints = new List<XConstraint>();
 10195502797      foreach (var xc in allX) {
 3391082798        if (xc.ConstraintName == "Equatable" || xc.ConstraintName == "EquatableArg") {
 62002799          var t0 = xc.Types[0].NormalizeExpandKeepConstraints();
 62002800          var t1 = xc.Types[1].NormalizeExpandKeepConstraints();
 62002801          if (proxiesOfInterest.Contains(t0) || proxiesOfInterest.Contains(t1)) {
 02802            ConstrainSubtypeRelation_Equal(t0, t1, xc.errorMsg);
 02803            anyNewConstraints = true;
 02804            continue;
 2805          }
 62002806        }
 3329082807        AllXConstraints.Add(xc);
 3329082808      }
 69422809      return anyNewConstraints;
 69422810    }
 2811
 263516572812    void ProcessOneSubtypingConstraintAndItsSubs(TypeConstraint c, ISet<TypeConstraint> processed, bool fullStrength, re
 2813      Contract.Requires(c != null);
 2814      Contract.Requires(processed != null);
 315949632815      if (processed.Contains(c)) {
 52433062816        return;  // our job has already been done, or is at least in progress
 2817      }
 211083512818      processed.Add(c);
 2819
 211083512820      var super = c.Super.NormalizeExpandKeepConstraints();
 211083512821      var sub = c.Sub.NormalizeExpandKeepConstraints();
 2822      // Process all subtype types before going on
 211083512823      var subProxy = sub as TypeProxy;
 414528122824      if (subProxy != null) {
 767274632825        foreach (var cc in subProxy.SubtypeConstraints) {
 52313602826          ProcessOneSubtypingConstraintAndItsSubs(cc, processed, fullStrength, ref anyNewConstraints);
 52313602827        }
 203444612828      }
 2829      // the processing may have assigned some proxies, so we'll refresh super and sub
 211083512830      super = super.NormalizeExpandKeepConstraints();
 211083512831      sub = sub.NormalizeExpandKeepConstraints();
 2832
 215596452833      if (super.Equals(sub)) {
 2834        // the constraint is satisfied, so just drop it
 212333972835      } else if ((super is NonProxyType || super is ArtificialType) && sub is NonProxyType) {
 1250462836        ImposeSubtypingConstraint(super, sub, c.ErrMsg);
 1250462837        anyNewConstraints = true;
 206570772838      } else if (AssignKnownEnd(sub as TypeProxy, true, fullStrength)) {
 202839        anyNewConstraints = true;
 205320112840      } else if (sub is TypeProxy && fullStrength && AssignKnownEndsFullstrength((TypeProxy)sub)) {
 02841        anyNewConstraints = true;
 205319912842      } else {
 2843        // keep the constraint for now
 205319912844        AllTypeConstraints.Add(c);
 205319912845      }
 263516572846    }
 2847
 3459052848    void ProcessFullStrength_SubDirection(Type t, ISet<TypeProxy> processed, ref bool anyNewConstraints) {
 2849      Contract.Requires(t != null);
 2850      Contract.Requires(processed != null);
 3459052851      var proxy = t.NormalizeExpand() as TypeProxy;
 4724902852      if (proxy != null) {
 1692502853        if (processed.Contains(proxy)) {
 426652854          return;  // our job has already been done, or is at least in progress
 2855        }
 839202856        processed.Add(proxy);
 2857
 4412852858        foreach (var u in proxy.SubtypesKeepConstraints_WithAssignable(AllXConstraints)) {
 631752859          ProcessFullStrength_SubDirection(u, processed, ref anyNewConstraints);
 631752860        }
 839202861        proxy = proxy.NormalizeExpand() as TypeProxy;
 839952862        if (proxy != null && AssignKnownEndsFullstrength_SubDirection(proxy)) {
 752863          anyNewConstraints = true;
 752864        }
 839202865      }
 3459052866    }
 2867
 4192262868    void ProcessFullStrength_SuperDirection(Type t, ISet<TypeProxy> processed, ref bool anyNewConstraints) {
 2869      Contract.Requires(t != null);
 2870      Contract.Requires(processed != null);
 4192262871      var proxy = t.NormalizeExpand() as TypeProxy;
 5763412872      if (proxy != null) {
 2004352873        if (processed.Contains(proxy)) {
 433202874          return;  // our job has already been done, or is at least in progress
 2875        }
 1137952876        processed.Add(proxy);
 2877
 8443832878        foreach (var u in proxy.Supertypes) {
 1676662879          ProcessFullStrength_SuperDirection(u, processed, ref anyNewConstraints);
 1676662880        }
 1137952881        proxy = proxy.NormalizeExpand() as TypeProxy;
 1762902882        if (proxy != null && AssignKnownEndsFullstrength_SuperDirection(proxy)) {
 624952883          anyNewConstraints = true;
 624952884        }
 1137952885      }
 4192262886    }
 2887
 2888    /// <summary>
 2889    /// Returns true if anything happened.
 2890    /// </summary>
 413482222891    bool AssignKnownEnd(TypeProxy proxy, bool keepConstraints, bool fullStrength) {
 2892      Contract.Requires(proxy == null || proxy.T == null);  // caller is supposed to have called NormalizeExpand
 567882432893      if (proxy == null) {
 2894        // nothing to do
 154400212895        return false;
 2896      }
 2897      // ----- first, go light; also, prefer subtypes over supertypes
 259082012898      IEnumerable<Type> subTypes = keepConstraints ? proxy.SubtypesKeepConstraints : proxy.Subtypes;
 1438826762899      foreach (var su in subTypes) {
 220782052900        DetermineRootLeaf(su, out var isRoot, out _, out var headRoot, out _);
 220782052901        Contract.Assert(!isRoot || headRoot);  // isRoot ==> headRoot
 221497672902        if (isRoot) {
 715622903          if (Reaches(su, proxy, 1, new HashSet<TypeProxy>())) {
 2904            // adding a constraint here would cause a bad cycle, so we don't
 715622905          } else {
 715622906            AssignProxyAndHandleItsConstraints(proxy, su, keepConstraints);
 715622907            return true;
 2908          }
 220116232909        } else if (headRoot) {
 49802910          if (Reaches(su, proxy, 1, new HashSet<TypeProxy>())) {
 2911            // adding a constraint here would cause a bad cycle, so we don't
 49802912          } else {
 49802913            AssignProxyAndHandleItsConstraints(proxy, TypeProxy.HeadWithProxyArgs(su), keepConstraints);
 49802914            return true;
 2915          }
 02916        }
 220016632917      }
 258316892918      if (fullStrength) {
 302919        IEnumerable<Type> superTypes = keepConstraints ? proxy.SupertypesKeepConstraints : proxy.Supertypes;
 1652920        foreach (var su in superTypes) {
 252921          DetermineRootLeaf(su, out _, out var isLeaf, out _, out var headLeaf);
 252922          Contract.Assert(!isLeaf || headLeaf);  // isLeaf ==> headLeaf
 252923          if (isLeaf) {
 02924            if (Reaches(su, proxy, -1, new HashSet<TypeProxy>())) {
 2925              // adding a constraint here would cause a bad cycle, so we don't
 02926            } else {
 02927              AssignProxyAndHandleItsConstraints(proxy, su, keepConstraints);
 02928              return true;
 2929            }
 252930          } else if (headLeaf) {
 02931            if (Reaches(su, proxy, -1, new HashSet<TypeProxy>())) {
 2932              // adding a constraint here would cause a bad cycle, so we don't
 02933            } else {
 02934              AssignProxyAndHandleItsConstraints(proxy, TypeProxy.HeadWithProxyArgs(su), keepConstraints);
 02935              return true;
 2936            }
 02937          }
 252938        }
 302939      }
 258316592940      return false;
 413482222941    }
 2942
 302943    bool AssignKnownEndsFullstrength(TypeProxy proxy) {
 2944      Contract.Requires(proxy != null);
 2945      // ----- continue with full strength
 2946      // If the join of the subtypes exists, use it
 302947      var joins = new List<Type>();
 2252948      foreach (var su in proxy.Subtypes) {
 902949        if (su is TypeProxy) {
 452950          continue;  // don't include proxies in the meet computation
 2951        }
 02952        int i = 0;
 02953        for (; i < joins.Count; i++) {
 02954          var j = Type.Join(joins[i], su, builtIns);
 02955          if (j != null) {
 02956            joins[i] = j;
 02957            break;
 2958          }
 02959        }
 02960        if (i == joins.Count) {
 2961          // we went to the end without finding a place to meet up
 02962          joins.Add(su);
 02963        }
 02964      }
 302965      if (joins.Count == 1 && !Reaches(joins[0], proxy, 1, new HashSet<TypeProxy>())) {
 2966        // we were able to compute a meet of all the subtyping constraints, so use it
 02967        AssignProxyAndHandleItsConstraints(proxy, joins[0]);
 02968        return true;
 2969      }
 2970      // If the meet of the supertypes exists, use it
 302971      var meets = new List<Type>();
 1652972      foreach (var su in proxy.Supertypes) {
 502973        if (su is TypeProxy) {
 252974          continue;  // don't include proxies in the meet computation
 2975        }
 02976        int i = 0;
 02977        for (; i < meets.Count; i++) {
 02978          var j = Type.Meet(meets[i], su, builtIns);
 02979          if (j != null) {
 02980            meets[i] = j;
 02981            break;
 2982          }
 02983        }
 02984        if (i == meets.Count) {
 2985          // we went to the end without finding a place to meet
 02986          meets.Add(su);
 02987        }
 02988      }
 302989      if (meets.Count == 1 && !(meets[0] is ArtificialType) && !Reaches(meets[0], proxy, -1, new HashSet<TypeProxy>())) 
 2990        // we were able to compute a meet of all the subtyping constraints, so use it
 02991        AssignProxyAndHandleItsConstraints(proxy, meets[0]);
 02992        return true;
 2993      }
 2994
 302995      return false;
 302996    }
 2997
 839202998    bool AssignKnownEndsFullstrength_SubDirection(TypeProxy proxy) {
 2999      Contract.Requires(proxy != null && proxy.T == null);
 3000      // If the join the subtypes exists, use it
 839203001      var joins = new List<Type>();
 839203002      var proxySubs = new HashSet<TypeProxy>();
 839203003      proxySubs.Add(proxy);
 4412853004      foreach (var su in proxy.SubtypesKeepConstraints_WithAssignable(AllXConstraints)) {
 1262153005        if (su is TypeProxy) {
 630403006          proxySubs.Add((TypeProxy)su);
 631753007        } else {
 1353008          int i = 0;
 1953009          for (; i < joins.Count; i++) {
 603010            var j = Type.Join(joins[i], su, builtIns);
 1203011            if (j != null) {
 603012              joins[i] = j;
 603013              break;
 3014            }
 03015          }
 2103016          if (i == joins.Count) {
 3017            // we went to the end without finding a place to join in
 753018            joins.Add(su);
 753019          }
 1353020        }
 631753021      }
 839953022      if (joins.Count == 1 && !Reaches(joins[0], proxy, 1, new HashSet<TypeProxy>())) {
 3023        // We were able to compute a join of all the subtyping constraints, so use it.
 3024        // Well, maybe.  If "join[0]" denotes a non-null type and "proxy" is something
 3025        // that could be assigned "null", then set "proxy" to the nullable version of "join[0]".
 3026        // Stated differently, think of an applicable "IsNullableRefType" constraint as
 3027        // being part of the join computation, essentially throwing in a "...?".
 3028        // Except: If the join is a tight bound--meaning, it is also a meet--then pick it
 3029        // after all, because that seems to give rise to less confusing error messages.
 1503030        if (joins[0].IsNonNullRefType) {
 753031          Type meet = null;
 753032          if (MeetOfAllSupertypes(proxy, ref meet, new HashSet<TypeProxy>(), false) && meet != null && Type.SameHead(joi
 3033            // leave it
 753034          } else {
 753035            CloseOverAssignableRhss(proxySubs);
 753036            if (HasApplicableNullableRefTypeConstraint(proxySubs)) {
 03037              if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 03038                Options.OutputWriter.WriteLine("DEBUG: Found join {0} for proxy {1}, but weakening it to {2}", joins[0],
 03039              }
 03040              AssignProxyAndHandleItsConstraints(proxy, joins[0].NormalizeExpand(), true);
 03041              return true;
 3042            }
 753043          }
 753044        }
 753045        AssignProxyAndHandleItsConstraints(proxy, joins[0], true);
 753046        return true;
 3047      }
 838453048      return false;
 839203049    }
 3050
 753051    private void CloseOverAssignableRhss(ISet<TypeProxy> proxySet) {
 3052      Contract.Requires(proxySet != null);
 1503053      while (true) {
 753054        var moreChanges = false;
 366603055        foreach (var xc in AllXConstraints) {
 183603056          if (xc.ConstraintName == "Assignable") {
 62153057            var source = xc.Types[0].Normalize() as TypeProxy;
 62153058            var sink = xc.Types[1].Normalize() as TypeProxy;
 62153059            if (source != null && sink != null && proxySet.Contains(source) && !proxySet.Contains(sink)) {
 03060              proxySet.Add(sink);
 03061              moreChanges = true;
 03062            }
 62153063          }
 121453064        }
 1503065        if (!moreChanges) {
 753066          return;
 3067        }
 03068      }
 753069    }
 753070    private bool HasApplicableNullableRefTypeConstraint(ISet<TypeProxy> proxySet) {
 3071      Contract.Requires(proxySet != null);
 753072      var nullableProxies = new HashSet<TypeProxy>();
 366603073      foreach (var xc in AllXConstraints) {
 121453074        if (xc.ConstraintName == "IsNullableRefType") {
 03075          var npr = xc.Types[0].Normalize() as TypeProxy;
 03076          if (npr != null) {
 03077            nullableProxies.Add(npr);
 03078          }
 03079        }
 121453080      }
 753081      return proxySet.Any(nullableProxies.Contains);
 753082    }
 2443083    private bool HasApplicableNullableRefTypeConstraint_SubDirection(TypeProxy proxy) {
 3084      Contract.Requires(proxy != null);
 2443085      var nullableProxies = new HashSet<TypeProxy>();
 14043086      foreach (var xc in AllXConstraints) {
 4483087        if (xc.ConstraintName == "IsNullableRefType") {
 2243088          var npr = xc.Types[0].Normalize() as TypeProxy;
 4483089          if (npr != null) {
 2243090            nullableProxies.Add(npr);
 2243091          }
 2243092        }
 2243093      }
 2443094      return HasApplicableNullableRefTypeConstraint_SubDirection_aux(proxy, nullableProxies, new HashSet<TypeProxy>());
 2443095    }
 2443096    private bool HasApplicableNullableRefTypeConstraint_SubDirection_aux(TypeProxy proxy, ISet<TypeProxy> nullableProxie
 3097      Contract.Requires(proxy != null);
 3098      Contract.Requires(nullableProxies != null);
 3099      Contract.Requires(visitedProxies != null);
 3100
 2443101      if (visitedProxies.Contains(proxy)) {
 03102        return false;
 3103      }
 2443104      visitedProxies.Add(proxy);
 3105
 4683106      if (nullableProxies.Contains(proxy)) {
 2243107        return true;
 3108      }
 3109
 603110      foreach (var sub in proxy.SubtypesKeepConstraints_WithAssignable(AllXConstraints)) {
 03111        var psub = sub as TypeProxy;
 03112        if (psub != null && HasApplicableNullableRefTypeConstraint_SubDirection_aux(psub, nullableProxies, visitedProxie
 03113          return true;
 3114        }
 03115      }
 203116      return false;
 2443117    }
 3118
 1028903119    bool AssignKnownEndsFullstrength_SuperDirection(TypeProxy proxy) {
 3120      Contract.Requires(proxy != null && proxy.T == null);
 3121      // First, compute the the join of the Assignable LHSs.  Then, compute
 3122      // the meet of that join and the supertypes.
 1028903123      var joins = new List<Type>();
 448624743124      foreach (var xc in AllXConstraints) {
 148872473125        if (xc.ConstraintName == "Assignable" && xc.Types[1].Normalize() == proxy) {
 359793126          var su = xc.Types[0].Normalize();
 457393127          if (su is TypeProxy) {
 97603128            continue; // don't include proxies in the join computation
 3129          }
 262193130          int i = 0;
 262193131          for (; i < joins.Count; i++) {
 03132            var j = Type.Join(joins[i], su, builtIns);
 03133            if (j != null) {
 03134              joins[i] = j;
 03135              break;
 3136            }
 03137          }
 524383138          if (i == joins.Count) {
 3139            // we went to the end without finding a place to join in
 262193140            joins.Add(su);
 262193141          }
 262193142        }
 148415083143      }
 3144      // If the meet of the supertypes exists, use it
 1028903145      var meets = new List<Type>(joins);
 7459983146      foreach (var su in proxy.SupertypesKeepConstraints) {
 1522113147        if (su is TypeProxy) {
 64353148          continue;  // don't include proxies in the meet computation
 3149        }
 1393413150        int i = 0;
 2032663151        for (; i < meets.Count; i++) {
 639253152          var j = Type.Meet(meets[i], su, builtIns);
 1278503153          if (j != null) {
 639253154            meets[i] = j;
 639253155            break;
 3156          }
 03157        }
 2147573158        if (i == meets.Count) {
 3159          // we went to the end without finding a place to meet up
 754163160          meets.Add(su);
 754163161        }
 1393413162      }
 1653853163      if (meets.Count == 1 && !(meets[0] is ArtificialType) && !Reaches(meets[0], proxy, -1, new HashSet<TypeProxy>())) 
 3164        // we were able to compute a meet of all the subtyping constraints, so use it
 624953165        AssignProxyAndHandleItsConstraints(proxy, meets[0], true);
 624953166        return true;
 3167      }
 403953168      return false;
 1028903169    }
 3170
 3171    int _reaches_recursion;
 2169653172    private bool Reaches(Type t, TypeProxy proxy, int direction, HashSet<TypeProxy> visited) {
 2169653173      if (_reaches_recursion == 20) {
 03174        Contract.Assume(false);  // possible infinite recursion
 03175      }
 2169653176      _reaches_recursion++;
 2169653177      var b = Reaches_aux(t, proxy, direction, visited);
 2169653178      _reaches_recursion--;
 2169653179      return b;
 2169653180    }
 2169653181    private bool Reaches_aux(Type t, TypeProxy proxy, int direction, HashSet<TypeProxy> visited) {
 3182      Contract.Requires(t != null);
 3183      Contract.Requires(proxy != null);
 3184      Contract.Requires(visited != null);
 2169653185      t = t.NormalizeExpand();
 2169653186      var tproxy = t as TypeProxy;
 4100203187      if (tproxy == null) {
 1930553188        var polarities = Type.GetPolarities(t).ConvertAll(TypeParameter.Direction);
 1930553189        Contract.Assert(polarities != null);
 1930553190        Contract.Assert(polarities.Count <= t.TypeArgs.Count);
 5086573191        for (int i = 0; i < polarities.Count; i++) {
 408493192          if (Reaches(t.TypeArgs[i], proxy, direction * polarities[i], visited)) {
 03193            return true;
 3194          }
 408493195        }
 1930553196        return false;
 243103197      } else if (tproxy == proxy) {
 4003198        return true;
 236953199      } else if (visited.Contains(tproxy)) {
 1853200        return false;
 233253201      } else {
 233253202        visited.Add(tproxy);
 401153203        if (0 <= direction && tproxy.Subtypes.Any(su => Reaches(su, proxy, direction, visited))) {
 03204          return true;
 3205        }
 233353206        if (direction <= 0 && tproxy.Supertypes.Any(su => Reaches(su, proxy, direction, visited))) {
 03207          return true;
 3208        }
 233253209        return false;
 3210      }
 2169653211    }
 3212
 3213    /// <summary>
 3214    /// Assumes type parameters have already been pushed, and that all types in class members have been resolved
 3215    /// </summary>
 7073216    void ResolveClassMemberBodiesInitial(TopLevelDeclWithMembers cl) {
 3217      Contract.Requires(cl != null);
 3218      Contract.Requires(currentClass == null);
 3219      Contract.Requires(AllTypeConstraints.Count == 0);
 3220      Contract.Ensures(currentClass == null);
 3221      Contract.Ensures(AllTypeConstraints.Count == 0);
 3222
 7073223      currentClass = cl;
 86043224      foreach (MemberDecl member in cl.Members) {
 21613225        Contract.Assert(VisibleInScope(member));
 21613226        if (member is ConstantField { Rhs: { } } constantField) {
 03227          var resolutionContext = new ResolutionContext(constantField, false);
 03228          scope.PushMarker();
 03229          if (constantField.IsStatic || currentClass == null || !currentClass.AcceptThis) {
 03230            scope.AllowInstance = false;
 03231          }
 03232          ResolveExpression(constantField.Rhs, resolutionContext);
 03233          scope.PopMarker();
 03234          AddAssignableConstraint(constantField.tok, constantField.Type, constantField.Rhs.Type,
 03235            "type for constant '" + constantField.Name + "' is '{0}', but its initialization value type is '{1}'");
 03236          SolveAllTypeConstraints();
 03237        }
 21613238      }
 7073239      currentClass = null;
 7073240    }
 3241
 3242    /// <summary>
 3243    /// Assumes type parameters have already been pushed, and that all types in class members have been resolved
 3244    /// </summary>
 7073245    void ResolveClassMemberBodies(TopLevelDeclWithMembers cl) {
 3246      Contract.Requires(cl != null);
 3247      Contract.Requires(currentClass == null);
 3248      Contract.Requires(AllTypeConstraints.Count == 0);
 3249      Contract.Ensures(currentClass == null);
 3250      Contract.Ensures(AllTypeConstraints.Count == 0);
 3251
 7073252      currentClass = cl;
 86043253      foreach (MemberDecl member in cl.Members) {
 21613254        Contract.Assert(VisibleInScope(member));
 22733255        if (member is Field) {
 1123256          var resolutionContext = new ResolutionContext(new NoContext(currentClass.EnclosingModuleDefinition), false);
 1123257          scope.PushMarker();
 1123258          if (member.IsStatic) {
 03259            scope.AllowInstance = false;
 03260          }
 1123261          ResolveAttributes(member, resolutionContext, true);
 1123262          scope.PopMarker();
 3263
 21613264        } else if (member is Function function) {
 03265          var ec = reporter.Count(ErrorLevel.Error);
 03266          allTypeParameters.PushMarker();
 03267          ResolveTypeParameters(function.TypeArgs, false, function);
 3268
 03269          function.Resolve(this);
 03270          allTypeParameters.PopMarker();
 03271          if (function is ExtremePredicate { PrefixPredicate: { } prefixPredicate } && ec == reporter.Count(ErrorLevel.E
 03272            allTypeParameters.PushMarker();
 03273            ResolveTypeParameters(prefixPredicate.TypeArgs, false, prefixPredicate);
 03274            prefixPredicate.Resolve(this);
 03275            allTypeParameters.PopMarker();
 03276          }
 3277
 40983278        } else if (member is Method method) {
 20493279          var ec = reporter.Count(ErrorLevel.Error);
 20493280          allTypeParameters.PushMarker();
 20493281          ResolveTypeParameters(method.TypeArgs, false, method);
 20493282          method.Resolve(this);
 20493283          allTypeParameters.PopMarker();
 20493284          if (method is ExtremeLemma { PrefixLemma: { } prefixLemma } && ec == reporter.Count(ErrorLevel.Error)) {
 03285            allTypeParameters.PushMarker();
 03286            ResolveTypeParameters(prefixLemma.TypeArgs, false, prefixLemma);
 03287            prefixLemma.Resolve(this);
 03288            allTypeParameters.PopMarker();
 03289          }
 3290
 20493291        } else {
 03292          Contract.Assert(false); throw new cce.UnreachableException();  // unexpected member type
 3293        }
 21613294        Contract.Assert(AllTypeConstraints.Count == 0);
 21613295      }
 7073296      currentClass = null;
 7073297    }
 3298
 3299    /// <summary>
 3300    /// Assumes type parameters have already been pushed
 3301    /// </summary>
 2693302    void ResolveCtorTypes(DatatypeDecl/*!*/ dt, Graph<IndDatatypeDecl/*!*/>/*!*/ dependencies, Graph<CoDatatypeDecl/*!*/
 3303      Contract.Requires(dt != null);
 3304      Contract.Requires(dependencies != null);
 3305      Contract.Requires(coDependencies != null);
 25893306      foreach (DatatypeCtor ctor in dt.Ctors) {
 3307
 5943308        ctor.EnclosingDatatype = dt;
 3309
 5943310        allTypeParameters.PushMarker();
 5943311        ResolveCtorSignature(ctor, dt.TypeArgs);
 5943312        allTypeParameters.PopMarker();
 3313
 11883314        if (dt is IndDatatypeDecl) {
 3315          // The dependencies of interest among inductive datatypes are all (inductive data)types mentioned in the param
 5943316          var idt = (IndDatatypeDecl)dt;
 5943317          dependencies.AddVertex(idt);
 35523318          foreach (Formal p in ctor.Formals) {
 5903319            AddDatatypeDependencyEdge(idt, p.Type, dependencies);
 5903320          }
 5943321        } else {
 3322          // The dependencies of interest among codatatypes are just the top-level types of parameters.
 03323          var codt = (CoDatatypeDecl)dt;
 03324          coDependencies.AddVertex(codt);
 03325          foreach (var p in ctor.Formals) {
 03326            var co = p.Type.AsCoDatatype;
 03327            if (co != null && codt.EnclosingModuleDefinition == co.EnclosingModuleDefinition) {
 03328              coDependencies.AddEdge(codt, co);
 03329            }
 03330          }
 03331        }
 5943332      }
 2693333    }
 3334
 5943335    void ResolveCtorSignature(DatatypeCtor ctor, List<TypeParameter> dtTypeArguments) {
 3336      Contract.Requires(ctor != null);
 3337      Contract.Requires(ctor.EnclosingDatatype != null);
 3338      Contract.Requires(dtTypeArguments != null);
 35523339      foreach (Formal p in ctor.Formals) {
 5903340        ResolveType(p.tok, p.Type, ctor.EnclosingDatatype, ResolveTypeOptionEnum.AllowPrefix, dtTypeArguments);
 5903341      }
 5943342    }
 3343
 5903344    void AddDatatypeDependencyEdge(IndDatatypeDecl dt, Type tp, Graph<IndDatatypeDecl> dependencies) {
 3345      Contract.Requires(dt != null);
 3346      Contract.Requires(tp != null);
 3347      Contract.Requires(dependencies != null);  // more expensive check: Contract.Requires(cce.NonNullElements(dependenc
 3348
 5903349      tp = tp.NormalizeExpand();
 5903350      var dependee = tp.AsIndDatatype;
 6303351      if (dependee != null && dt.EnclosingModuleDefinition == dependee.EnclosingModuleDefinition) {
 403352        dependencies.AddEdge(dt, dependee);
 1203353        foreach (var ta in ((UserDefinedType)tp).TypeArgs) {
 03354          AddDatatypeDependencyEdge(dt, ta, dependencies);
 03355        }
 403356      }
 5903357    }
 3358
 03359    public void ResolveFrameExpressionTopLevel(FrameExpression fe, FrameExpressionUse use, ICodeContext codeContext) {
 03360      ResolveFrameExpression(fe, use, new ResolutionContext(codeContext, false));
 03361    }
 3362
 03363    void ResolveFrameExpression(FrameExpression fe, FrameExpressionUse use, ResolutionContext resolutionContext) {
 3364      Contract.Requires(fe != null);
 3365      Contract.Requires(resolutionContext != null);
 3366
 03367      ResolveExpression(fe.E, resolutionContext);
 03368      Type t = fe.E.Type;
 03369      Contract.Assert(t != null);  // follows from postcondition of ResolveExpression
 03370      var eventualRefType = new InferredTypeProxy();
 03371      if (use == FrameExpressionUse.Reads) {
 03372        AddXConstraint(fe.E.tok, "ReadsFrame", t, eventualRefType,
 03373          "a reads-clause expression must denote an object, a set/iset/multiset/seq of objects, or a function to a set/i
 03374      } else {
 03375        AddXConstraint(fe.E.tok, "ModifiesFrame", t, eventualRefType,
 03376          use == FrameExpressionUse.Modifies ?
 03377          "a modifies-clause expression must denote an object or a set/iset/multiset/seq of objects (instead got {0})" :
 03378          "an unchanged expression must denote an object or a set/iset/multiset/seq of objects (instead got {0})");
 03379      }
 03380      if (fe.FieldName != null) {
 03381        var member = ResolveMember(fe.E.tok, eventualRefType, fe.FieldName, out var tentativeReceiverType);
 03382        var ctype = (UserDefinedType)tentativeReceiverType;  // correctness of cast follows from the DenotesClass test a
 03383        if (member == null) {
 3384          // error has already been reported by ResolveMember
 03385        } else if (!(member is Field)) {
 03386          reporter.Error(MessageSource.Resolver, fe.E, "member {0} in type {1} does not refer to a field", fe.FieldName,
 03387        } else if (member is ConstantField) {
 03388          reporter.Error(MessageSource.Resolver, fe.E, "expression is not allowed to refer to constant field {0}", fe.Fi
 03389        } else {
 03390          Contract.Assert(ctype != null && ctype.ResolvedClass != null);  // follows from postcondition of ResolveMember
 03391          fe.Field = (Field)member;
 03392        }
 03393      }
 03394    }
 3395
 03396    void ResolveIterator(IteratorDecl iter) {
 3397      Contract.Requires(iter != null);
 3398      Contract.Requires(currentClass == null);
 3399      Contract.Ensures(currentClass == null);
 3400
 03401      var initialErrorCount = reporter.Count(ErrorLevel.Error);
 3402
 3403      // Add in-parameters to the scope, but don't care about any duplication errors, since they have already been repor
 03404      scope.PushMarker();
 03405      scope.AllowInstance = false;  // disallow 'this' from use, which means that the special fields and methods added a
 03406      iter.Ins.ForEach(p => scope.Push(p.Name, p));
 03407      ResolveParameterDefaultValues(iter.Ins, new ResolutionContext(iter, false));
 3408
 3409      // Start resolving specification...
 3410      // we start with the decreases clause, because the _decreases<n> fields were only given type proxies before; we'll
 3411      // the types only after resolving the decreases clause (and it may be that some of resolution has already seen use
 3412      // these fields; so, with no further ado, here we go
 03413      ResolveAttributes(iter.Decreases, new ResolutionContext(iter, false));
 03414      Contract.Assert(iter.Decreases.Expressions.Count == iter.DecreasesFields.Count);
 03415      for (var i = 0; i < iter.Decreases.Expressions.Count; i++) {
 03416        var e = iter.Decreases.Expressions[i];
 03417        ResolveExpression(e, new ResolutionContext(iter, false));
 3418        // any type is fine, but associate this type with the corresponding _decreases<n> field
 03419        var d = iter.DecreasesFields[i];
 3420        // If the following type constraint does not hold, then: Bummer, there was a use--and a bad use--of the field be
 03421        ConstrainSubtypeRelation(d.Type, e.Type, e, "type of field {0} is {1}, but has been constrained elsewhere to be 
 03422      }
 03423      foreach (FrameExpression fe in iter.Reads.Expressions) {
 03424        ResolveFrameExpressionTopLevel(fe, FrameExpressionUse.Reads, iter);
 03425      }
 03426      ResolveAttributes(iter.Modifies, new ResolutionContext(iter, false));
 03427      foreach (FrameExpression fe in iter.Modifies.Expressions) {
 03428        ResolveFrameExpressionTopLevel(fe, FrameExpressionUse.Modifies, iter);
 03429      }
 03430      foreach (AttributedExpression e in iter.Requires) {
 03431        ResolveAttributes(e, new ResolutionContext(iter, false));
 03432        ResolveExpression(e.E, new ResolutionContext(iter, false));
 03433        Contract.Assert(e.E.Type != null);  // follows from postcondition of ResolveExpression
 03434        ConstrainTypeExprBool(e.E, "Precondition must be a boolean (got {0})");
 03435      }
 3436
 03437      scope.PopMarker();  // for the in-parameters
 3438
 3439      // We resolve the rest of the specification in an instance context.  So mentions of the in- or yield-parameters
 3440      // get resolved as field dereferences (with an implicit "this")
 03441      scope.PushMarker();
 03442      currentClass = iter;
 03443      Contract.Assert(scope.AllowInstance);
 3444
 03445      foreach (AttributedExpression e in iter.YieldRequires) {
 03446        ResolveAttributes(e, new ResolutionContext(iter, false));
 03447        ResolveExpression(e.E, new ResolutionContext(iter, false));
 03448        Contract.Assert(e.E.Type != null);  // follows from postcondition of ResolveExpression
 03449        ConstrainTypeExprBool(e.E, "Yield precondition must be a boolean (got {0})");
 03450      }
 03451      foreach (AttributedExpression e in iter.YieldEnsures) {
 03452        ResolveAttributes(e, new ResolutionContext(iter, true));
 03453        ResolveExpression(e.E, new ResolutionContext(iter, true));
 03454        Contract.Assert(e.E.Type != null);  // follows from postcondition of ResolveExpression
 03455        ConstrainTypeExprBool(e.E, "Yield postcondition must be a boolean (got {0})");
 03456      }
 03457      foreach (AttributedExpression e in iter.Ensures) {
 03458        ResolveAttributes(e, new ResolutionContext(iter, true));
 03459        ResolveExpression(e.E, new ResolutionContext(iter, true));
 03460        Contract.Assert(e.E.Type != null);  // follows from postcondition of ResolveExpression
 03461        ConstrainTypeExprBool(e.E, "Postcondition must be a boolean (got {0})");
 03462      }
 03463      SolveAllTypeConstraints();
 3464
 03465      var postSpecErrorCount = reporter.Count(ErrorLevel.Error);
 3466
 3467      // Resolve body
 03468      if (iter.Body != null) {
 03469        DominatingStatementLabels.PushMarker();
 03470        foreach (var req in iter.Requires) {
 03471          if (req.Label != null) {
 03472            if (DominatingStatementLabels.Find(req.Label.Name) != null) {
 03473              reporter.Error(MessageSource.Resolver, req.Label.Tok, "assert label shadows a dominating label");
 03474            } else {
 03475              var rr = DominatingStatementLabels.Push(req.Label.Name, req.Label);
 03476              Contract.Assert(rr == Scope<Label>.PushResult.Success);  // since we just checked for duplicates, we expec
 03477            }
 03478          }
 03479        }
 03480        ResolveBlockStatement(iter.Body, ResolutionContext.FromCodeContext(iter));
 03481        DominatingStatementLabels.PopMarker();
 03482        SolveAllTypeConstraints();
 03483      }
 3484
 03485      currentClass = null;
 03486      scope.PopMarker();  // pop off the AllowInstance setting
 3487
 03488      if (postSpecErrorCount == initialErrorCount) {
 03489        iter.CreateIteratorMethodSpecs(this);
 03490      }
 03491    }
 3492
 3493    /// <summary>
 3494    /// Checks if lhs, which is expected to be a successfully resolved expression, denotes something
 3495    /// that can be assigned to.  In particular, this means that lhs denotes a mutable variable, field,
 3496    /// or array element.  If a violation is detected, an error is reported.
 3497    /// </summary>
 593753498    public void CheckIsLvalue(Expression lhs, ResolutionContext resolutionContext) {
 3499      Contract.Requires(lhs != null);
 3500      Contract.Requires(resolutionContext != null);
 1171203501      if (lhs is IdentifierExpr) {
 577453502        var ll = (IdentifierExpr)lhs;
 577453503        if (!ll.Var.IsMutable) {
 03504          reporter.Error(MessageSource.Resolver, lhs, "LHS of assignment must denote a mutable variable");
 03505        }
 593753506      } else if (lhs is MemberSelectExpr) {
 03507        var ll = (MemberSelectExpr)lhs;
 03508        var field = ll.Member as Field;
 03509        if (field == null || !field.IsUserMutable) {
 03510          if (resolutionContext.InFirstPhaseConstructor && field is ConstantField cf && !cf.IsStatic && cf.Rhs == null) 
 03511            if (Expression.AsThis(ll.Obj) != null) {
 3512              // it's cool; this field can be assigned to here
 03513            } else {
 03514              reporter.Error(MessageSource.Resolver, lhs, "LHS of assignment must denote a mutable field of 'this'");
 03515            }
 03516          } else {
 03517            reporter.Error(MessageSource.Resolver, lhs, "LHS of assignment must denote a mutable field");
 03518          }
 03519        }
 32603520      } else if (lhs is SeqSelectExpr) {
 16303521        var ll = (SeqSelectExpr)lhs;
 16303522        ConstrainSubtypeRelation(ResolvedArrayType(ll.Seq.tok, 1, new InferredTypeProxy(), resolutionContext, true), ll.
 16303523          "LHS of array assignment must denote an array element (found {0})", ll.Seq.Type);
 16303524        if (!ll.SelectOne) {
 03525          reporter.Error(MessageSource.Resolver, ll.Seq, "cannot assign to a range of array elements (try the 'forall' s
 03526        }
 16303527      } else if (lhs is MultiSelectExpr) {
 3528        // nothing to check; this can only denote an array element
 03529      } else {
 03530        reporter.Error(MessageSource.Resolver, lhs, "LHS of assignment must denote a mutable variable or field");
 03531      }
 593753532    }
 3533
 47673534    public void ResolveBlockStatement(BlockStmt blockStmt, ResolutionContext resolutionContext) {
 3535      Contract.Requires(blockStmt != null);
 3536      Contract.Requires(resolutionContext != null);
 3537
 47673538      if (blockStmt is DividedBlockStmt) {
 03539        var div = (DividedBlockStmt)blockStmt;
 03540        Contract.Assert(currentMethod is Constructor);  // divided bodies occur only in class constructors
 03541        Contract.Assert(!resolutionContext.InFirstPhaseConstructor);  // divided bodies are never nested
 03542        foreach (Statement ss in div.BodyInit) {
 03543          ResolveStatementWithLabels(ss, resolutionContext with { InFirstPhaseConstructor = true });
 03544        }
 03545        foreach (Statement ss in div.BodyProper) {
 03546          ResolveStatementWithLabels(ss, resolutionContext);
 03547        }
 47673548      } else {
 1933323549        foreach (Statement ss in blockStmt.Body) {
 596773550          ResolveStatementWithLabels(ss, resolutionContext);
 596773551        }
 47673552      }
 47673553    }
 3554
 600023555    public void ResolveStatementWithLabels(Statement stmt, ResolutionContext resolutionContext) {
 3556      Contract.Requires(stmt != null);
 3557      Contract.Requires(resolutionContext != null);
 3558
 600023559      enclosingStatementLabels.PushMarker();
 3560      // push labels
 1200043561      for (var l = stmt.Labels; l != null; l = l.Next) {
 03562        var lnode = l.Data;
 03563        Contract.Assert(lnode.Name != null);  // LabelNode's with .Label==null are added only during resolution of the b
 03564        var prev = enclosingStatementLabels.Find(lnode.Name);
 03565        if (prev == stmt) {
 03566          reporter.Error(MessageSource.Resolver, lnode.Tok, "duplicate label");
 03567        } else if (prev != null) {
 03568          reporter.Error(MessageSource.Resolver, lnode.Tok, "label shadows an enclosing label");
 03569        } else {
 03570          var r = enclosingStatementLabels.Push(lnode.Name, stmt);
 03571          Contract.Assert(r == Scope<Statement>.PushResult.Success);  // since we just checked for duplicates, we expect
 03572          if (DominatingStatementLabels.Find(lnode.Name) != null) {
 03573            reporter.Error(MessageSource.Resolver, lnode.Tok, "label shadows a dominating label");
 03574          } else {
 03575            var rr = DominatingStatementLabels.Push(lnode.Name, lnode);
 03576            Contract.Assert(rr == Scope<Label>.PushResult.Success);  // since we just checked for duplicates, we expect 
 03577          }
 03578        }
 03579      }
 600023580      ResolveStatement(stmt, resolutionContext);
 600023581      enclosingStatementLabels.PopMarker();
 600023582    }
 3583
 03584    void ResolveAlternatives(List<GuardedAlternative> alternatives, AlternativeLoopStmt loopToCatchBreaks, ResolutionCon
 3585      Contract.Requires(alternatives != null);
 3586      Contract.Requires(resolutionContext != null);
 3587
 3588      // first, resolve the guards
 03589      foreach (var alternative in alternatives) {
 03590        int prevErrorCount = reporter.Count(ErrorLevel.Error);
 03591        ResolveExpression(alternative.Guard, resolutionContext);
 03592        Contract.Assert(alternative.Guard.Type != null);  // follows from postcondition of ResolveExpression
 03593        bool successfullyResolved = reporter.Count(ErrorLevel.Error) == prevErrorCount;
 03594        ConstrainTypeExprBool(alternative.Guard, "condition is expected to be of type bool, but is {0}");
 03595      }
 3596
 03597      if (loopToCatchBreaks != null) {
 03598        loopStack.Add(loopToCatchBreaks);  // push
 03599      }
 03600      foreach (var alternative in alternatives) {
 03601        scope.PushMarker();
 03602        DominatingStatementLabels.PushMarker();
 03603        if (alternative.IsBindingGuard) {
 03604          var exists = (ExistsExpr)alternative.Guard;
 03605          foreach (var v in exists.BoundVars) {
 03606            ScopePushAndReport(scope, v, "bound-variable");
 03607          }
 03608        }
 03609        ResolveAttributes(alternative, resolutionContext);
 03610        foreach (Statement ss in alternative.Body) {
 03611          ResolveStatementWithLabels(ss, resolutionContext);
 03612        }
 03613        DominatingStatementLabels.PopMarker();
 03614        scope.PopMarker();
 03615      }
 03616      if (loopToCatchBreaks != null) {
 03617        loopStack.RemoveAt(loopStack.Count - 1);  // pop
 03618      }
 03619    }
 3620
 3621    /// <summary>
 3622    /// Resolves the given call statement.
 3623    /// Assumes all LHSs have already been resolved (and checked for mutability).
 3624    /// </summary>
 34713625    void ResolveCallStmt(CallStmt s, ResolutionContext resolutionContext, Type receiverType) {
 3626      Contract.Requires(s != null);
 3627      Contract.Requires(resolutionContext != null);
 34713628      bool isInitCall = receiverType != null;
 3629
 34713630      var callee = s.Method;
 34713631      Contract.Assert(callee != null);  // follows from the invariant of CallStmt
 34713632      if (!isInitCall && callee is Constructor) {
 03633        reporter.Error(MessageSource.Resolver, s, "a constructor is allowed to be called only when an object is being al
 03634      }
 3635
 3636      // resolve left-hand sides (the right-hand sides are resolved below)
 218313637      foreach (var lhs in s.Lhs) {
 38063638        Contract.Assume(lhs.Type != null);  // a sanity check that LHSs have already been resolved
 38063639      }
 3640
 34713641      bool tryToResolve = false;
 34713642      if (callee.Outs.Count != s.Lhs.Count) {
 03643        if (isInitCall) {
 03644          reporter.Error(MessageSource.Resolver, s, "a method called as an initialization method must not have any resul
 03645        } else {
 03646          reporter.Error(MessageSource.Resolver, s, "wrong number of method result arguments (got {0}, expected {1})", s
 03647          tryToResolve = true;
 03648        }
 34713649      } else {
 34713650        if (isInitCall) {
 03651          if (callee.IsStatic) {
 03652            reporter.Error(MessageSource.Resolver, s.Tok, "a method called as an initialization method must not be 'stat
 03653          } else {
 03654            tryToResolve = true;
 03655          }
 34713656        } else if (!callee.IsStatic) {
 03657          if (!scope.AllowInstance && s.Receiver is ThisExpr) {
 3658            // The call really needs an instance, but that instance is given as 'this', which is not
 3659            // available in this context.  For more details, see comment in the resolution of a
 3660            // FunctionCallExpr.
 03661            reporter.Error(MessageSource.Resolver, s.Receiver, "'this' is not allowed in a 'static' context");
 03662          } else if (s.Receiver is StaticReceiverExpr) {
 03663            reporter.Error(MessageSource.Resolver, s.Receiver, "call to instance method requires an instance");
 03664          } else {
 03665            tryToResolve = true;
 03666          }
 34713667        } else {
 34713668          tryToResolve = true;
 34713669        }
 34713670      }
 3671
 69423672      if (tryToResolve) {
 34713673        var typeMap = s.MethodSelect.TypeArgumentSubstitutionsAtMemberDeclaration();
 3674        // resolve arguments
 34713675        ResolveActualParameters(s.Bindings, callee.Ins, s.Tok, callee, resolutionContext, typeMap,
 34713676          callee.IsStatic ? null : s.Receiver);
 3677        // type check the out-parameter arguments (in-parameters were type checked as part of ResolveActualParameters)
 183603678        for (int i = 0; i < callee.Outs.Count && i < s.Lhs.Count; i++) {
 38063679          var outFormal = callee.Outs[i];
 38063680          var it = outFormal.Type;
 38063681          Type st = it.Subst(typeMap);
 38063682          var lhs = s.Lhs[i];
 38063683          var what = GetLocationInformation(outFormal, callee.Outs.Count(), i, "method out-parameter");
 3684
 38063685          AddAssignableConstraint(
 38063686            s.Tok, lhs.Type, st,
 38063687            $"incorrect return type {what} (expected {{1}}, got {{0}})");
 38063688        }
 183603689        for (int i = 0; i < s.Lhs.Count; i++) {
 38063690          var lhs = s.Lhs[i];
 3691          // LHS must denote a mutable field.
 38063692          CheckIsLvalue(lhs.Resolved, resolutionContext);
 38063693        }
 34713694      }
 34713695      if (Contract.Exists(callee.Decreases.Expressions, e => e is WildcardExpr) && !resolutionContext.CodeContext.Allows
 03696        reporter.Error(MessageSource.Resolver, s.Tok, "a call to a possibly non-terminating method is allowed only if th
 03697      }
 34713698    }
 3699
 3700    /// <summary>
 3701    /// Resolve the actual arguments given in "bindings". Then, check that there is exactly one
 3702    /// actual for each formal, and impose assignable constraints.
 3703    /// "typeMap" is applied to the type of each formal.
 3704    /// This method should be called only once. That is, bindings.arguments is required to be null on entry to this meth
 3705    /// </summary>
 3706    void ResolveActualParameters(ActualBindings bindings, List<Formal> formals, IToken callTok, object context, Resoluti
 157453707      Dictionary<TypeParameter, Type> typeMap, Expression/*?*/ receiver) {
 3708      Contract.Requires(bindings != null);
 3709      Contract.Requires(formals != null);
 3710      Contract.Requires(callTok != null);
 3711      Contract.Requires(context is Method || context is Function || context is DatatypeCtor || context is ArrowType);
 3712      Contract.Requires(typeMap != null);
 3713      Contract.Requires(!bindings.WasResolved);
 3714
 3715      string whatKind;
 3716      string name;
 192163717      if (context is Method cMethod) {
 34713718        whatKind = cMethod.WhatKind;
 34713719        name = $"{whatKind} '{cMethod.Name}'";
 157453720      } else if (context is Function cFunction) {
 03721        whatKind = cFunction.WhatKind;
 03722        name = $"{whatKind} '{cFunction.Name}'";
 245483723      } else if (context is DatatypeCtor cCtor) {
 122743724        whatKind = "datatype constructor";
 122743725        name = $"{whatKind} '{cCtor.Name}'";
 122743726      } else {
 03727        var cArrowType = (ArrowType)context;
 03728        whatKind = "function application";
 03729        name = $"function type '{cArrowType}'";
 03730      }
 3731
 3732      // If all arguments are passed positionally, use simple error messages that talk about the count of arguments.
 466253733      var onlyPositionalArguments = bindings.ArgumentBindings.TrueForAll(binding => binding.FormalParameterName == null)
 157453734      var simpleErrorReported = false;
 314903735      if (onlyPositionalArguments) {
 466253736        var requiredParametersCount = formals.Count(f => f.DefaultValue == null);
 157453737        var actualsCounts = bindings.ArgumentBindings.Count;
 157453738        var sig = "";
 1241303739        for (int i = 0; i < formals.Count; i++) {
 308803740          sig += (", " + formals[i].Name + ": " + formals[i].Type.ToString());
 308803741        }
 280563742        if (formals.Count > 0) {
 123113743          sig = ": (" + sig[2..] + ")";
 123113744        }
 314903745        if (requiredParametersCount <= actualsCounts && actualsCounts <= formals.Count) {
 3746          // the situation is plausible
 157453747        } else if (requiredParametersCount == formals.Count) {
 3748          // this is the common, classical case of no default parameter values; generate a straightforward error message
 03749          reporter.Error(MessageSource.Resolver, callTok, $"wrong number of arguments (got {actualsCounts}, but {name} e
 03750          simpleErrorReported = true;
 03751        } else if (actualsCounts < requiredParametersCount) {
 03752          reporter.Error(MessageSource.Resolver, callTok, $"wrong number of arguments (got {actualsCounts}, but {name} e
 03753          simpleErrorReported = true;
 03754        } else {
 03755          reporter.Error(MessageSource.Resolver, callTok, $"wrong number of arguments (got {actualsCounts}, but {name} e
 03756          simpleErrorReported = true;
 03757        }
 157453758      }
 3759
 3760      // resolve given arguments and populate the "namesToActuals" map
 157453761      var namesToActuals = new Dictionary<string, ActualBinding>();
 466253762      formals.ForEach(f => namesToActuals.Add(f.Name, null)); // a name mapping to "null" says it hasn't been filled in 
 157453763      var stillAcceptingPositionalArguments = true;
 157453764      var bindingIndex = 0;
 1398753765      foreach (var binding in bindings.ArgumentBindings) {
 308803766        var arg = binding.Actual;
 3767        // insert the actual into "namesToActuals" under an appropriate name, unless there is an error
 308803768        if (binding.FormalParameterName != null) {
 03769          var pname = binding.FormalParameterName.val;
 03770          stillAcceptingPositionalArguments = false;
 03771          if (!namesToActuals.TryGetValue(pname, out var b)) {
 03772            reporter.Error(MessageSource.Resolver, binding.FormalParameterName, $"the binding named '{pname}' does not c
 03773          } else if (b == null) {
 3774            // all is good
 03775            namesToActuals[pname] = binding;
 03776          } else if (b.FormalParameterName == null) {
 03777            reporter.Error(MessageSource.Resolver, binding.FormalParameterName, $"the parameter named '{pname}' is alrea
 03778          } else {
 03779            reporter.Error(MessageSource.Resolver, binding.FormalParameterName, $"duplicate binding for parameter name '
 03780          }
 308803781        } else if (!stillAcceptingPositionalArguments) {
 03782          reporter.Error(MessageSource.Resolver, arg.tok, "a positional argument is not allowed to follow named argument
 617603783        } else if (bindingIndex < formals.Count) {
 3784          // use the name of formal corresponding to this positional argument, unless the parameter is named-only
 308803785          var formal = formals[bindingIndex];
 308803786          var pname = formal.Name;
 308803787          if (formal.IsNameOnly) {
 03788            reporter.Error(MessageSource.Resolver, arg.tok,
 03789              $"nameonly parameter '{pname}' must be passed using a name binding; it cannot be passed positionally");
 03790          }
 308803791          Contract.Assert(namesToActuals[pname] == null); // we expect this, since we've only filled parameters position
 308803792          namesToActuals[pname] = binding;
 308803793        } else {
 3794          // too many positional arguments
 03795          if (onlyPositionalArguments) {
 3796            // error was reported before the "foreach" loop
 03797            Contract.Assert(simpleErrorReported);
 03798          } else if (formals.Count < bindingIndex) {
 3799            // error was reported on a previous iteration of this "foreach" loop
 03800          } else {
 03801            reporter.Error(MessageSource.Resolver, callTok,
 03802              $"wrong number of arguments ({name} expects {formals.Count}, got {bindings.ArgumentBindings.Count})");
 03803          }
 03804        }
 3805
 3806        // resolve argument
 308803807        ResolveExpression(arg, resolutionContext);
 308803808        bindingIndex++;
 308803809      }
 3810
 157453811      var actuals = new List<Expression>();
 157453812      var formalIndex = 0;
 157453813      var substMap = new Dictionary<IVariable, Expression>();
 1398753814      foreach (var formal in formals) {
 308803815        var b = namesToActuals[formal.Name];
 617603816        if (b != null) {
 308803817          actuals.Add(b.Actual);
 308803818          substMap.Add(formal, b.Actual);
 308803819          var what = GetLocationInformation(formal,
 308803820            bindings.ArgumentBindings.Count(), bindings.ArgumentBindings.IndexOf(b),
 308803821            whatKind + (context is Method ? " in-parameter" : " parameter"));
 3822
 308803823          AddAssignableConstraint(
 308803824            callTok, formal.Type.Subst(typeMap), b.Actual.Type,
 308803825            $"incorrect argument type {what} (expected {{0}}, found {{1}})");
 308803826        } else if (formal.DefaultValue != null) {
 3827          // Note, in the following line, "substMap" is passed in, but it hasn't been fully filled in until the
 3828          // end of this foreach loop. Still, that's soon enough, because DefaultValueExpression won't use it
 3829          // until FillInDefaultValueExpressions at the end of Pass 1 of the Resolver.
 03830          var n = new DefaultValueExpression(callTok, formal, receiver, substMap, typeMap);
 03831          allDefaultValueExpressions.Add(n);
 03832          actuals.Add(n);
 03833          substMap.Add(formal, n);
 03834        } else {
 3835          // parameter has no value
 03836          if (onlyPositionalArguments) {
 3837            // a simple error message has already been reported
 03838            Contract.Assert(simpleErrorReported);
 03839          } else {
 03840            var formalDescription = whatKind + (context is Method ? " in-parameter" : " parameter");
 03841            var nameWithIndex = formal.HasName && formal is not ImplicitFormal ? "'" + formal.Name + "'" : "";
 03842            if (formals.Count > 1 || nameWithIndex == "") {
 03843              nameWithIndex += nameWithIndex == "" ? "" : " ";
 03844              nameWithIndex += $"at index {formalIndex}";
 03845            }
 03846            var message = $"{formalDescription} {nameWithIndex} requires an argument of type {formal.Type}";
 03847            reporter.Error(MessageSource.Resolver, callTok, message);
 03848          }
 03849        }
 308803850        formalIndex++;
 308803851      }
 3852
 157453853      bindings.AcceptArgumentExpressionsAsExactParameterList(actuals);
 157453854    }
 3855
 346863856    private static string GetLocationInformation(Formal parameter, int bindingCount, int bindingIndex, string formalDesc
 346863857      var displayName = parameter.HasName && parameter is not ImplicitFormal;
 346863858      var description = "";
 655173859      if (bindingCount > 1) {
 308313860        description += $"at index {bindingIndex} ";
 308313861      }
 3862
 346863863      description += $"for {formalDescription}";
 3864
 693723865      if (displayName) {
 346863866        description += $" '{parameter.Name}'";
 346863867      }
 3868
 346863869      return description;
 346863870    }
 3871
 3872    /// <summary>
 3873    /// To resolve "id" in expression "E . id", do:
 3874    ///  * If E denotes a module name M:
 3875    ///      0. Member of module M:  sub-module (including submodules of imports), class, datatype, etc.
 3876    ///         (if two imported types have the same name, an error message is produced here)
 3877    ///      1. Static member of M._default denoting an async task type
 3878    ///    (Note that in contrast to ResolveNameSegment_Type, imported modules, etc. are ignored)
 3879    ///  * If E denotes a type:
 3880    ///      2. a. Member of that type denoting an async task type, or:
 3881    ///         b. If allowDanglingDotName:
 3882    ///            Return the type "E" and the given "expr", letting the caller try to make sense of the final dot-name.
 3883    ///
 3884    /// Note: 1 and 2a are not used now, but they will be of interest when async task types are supported.
 3885    /// </summary>
 03886    ResolveTypeReturn ResolveDotSuffix_Type(ExprDotName expr, ResolutionContext resolutionContext, bool allowDanglingDot
 3887      Contract.Requires(expr != null);
 3888      Contract.Requires(!expr.WasResolved());
 3889      Contract.Requires(expr.Lhs is NameSegment || expr.Lhs is ExprDotName);
 3890      Contract.Requires(resolutionContext != null);
 3891      Contract.Ensures(Contract.Result<ResolveTypeReturn>() == null || allowDanglingDotName);
 3892
 3893      // resolve the LHS expression
 03894      if (expr.Lhs is NameSegment) {
 03895        ResolveNameSegment_Type((NameSegment)expr.Lhs, resolutionContext, option, defaultTypeArguments);
 03896      } else {
 03897        ResolveDotSuffix_Type((ExprDotName)expr.Lhs, resolutionContext, false, option, defaultTypeArguments);
 03898      }
 3899
 03900      if (expr.OptTypeArguments != null) {
 03901        foreach (var ty in expr.OptTypeArguments) {
 03902          ResolveType(expr.tok, ty, resolutionContext, option, defaultTypeArguments);
 03903        }
 03904      }
 3905
 03906      Expression r = null;  // the resolved expression, if successful
 3907
 03908      var lhs = expr.Lhs.Resolved;
 03909      if (lhs != null && lhs.Type is Resolver_IdentifierExpr.ResolverType_Module) {
 03910        var ri = (Resolver_IdentifierExpr)lhs;
 03911        var sig = ((ModuleDecl)ri.Decl).AccessibleSignature(useCompileSignatures);
 03912        sig = GetSignature(sig);
 3913        // For 0:
 3914
 03915        if (sig.TopLevels.TryGetValue(expr.SuffixName, out var decl)) {
 3916          // ----- 0. Member of the specified module
 03917          if (decl is AmbiguousTopLevelDecl) {
 03918            var ad = (AmbiguousTopLevelDecl)decl;
 03919            reporter.Error(MessageSource.Resolver, expr.tok, "The name {0} ambiguously refers to a type in one of the mo
 03920          } else {
 3921            // We have found a module name or a type name.  We create a temporary expression that will never be seen by 
 3922            // or verifier, just to have a placeholder where we can recorded what we have found.
 03923            r = CreateResolver_IdentifierExpr(expr.tok, expr.SuffixName, expr.OptTypeArguments, decl);
 03924          }
 3925#if ASYNC_TASK_TYPES
 3926        } else if (sig.StaticMembers.TryGetValue(expr.SuffixName, out member)) {
 3927          // ----- 1. static member of the specified module
 3928          Contract.Assert(member.IsStatic); // moduleInfo.StaticMembers is supposed to contain only static members of th
 3929          if (ReallyAmbiguousThing(ref member)) {
 3930            reporter.Error(MessageSource.Resolver, expr.tok, "The name {0} ambiguously refers to a static member in one 
 3931          } else {
 3932            var receiver = new StaticReceiverExpr(expr.tok, (ClassDecl)member.EnclosingClass);
 3933            r = ResolveExprDotCall(expr.tok, receiver, member, expr.OptTypeArguments, opts.resolutionContext, allowMetho
 3934          }
 3935#endif
 03936        } else {
 03937          reporter.Error(MessageSource.Resolver, expr.tok, "module '{0}' does not declare a type '{1}'", ri.Decl.Name, e
 03938        }
 3939
 03940      } else if (lhs != null && lhs.Type is Resolver_IdentifierExpr.ResolverType_Type) {
 03941        var ri = (Resolver_IdentifierExpr)lhs;
 3942        // ----- 2. Look up name in type
 03943        var ty = new UserDefinedType(ri.tok, ri.Decl.Name, ri.Decl, ri.TypeArgs);
 03944        if (allowDanglingDotName && ty.IsRefType) {
 03945          return new ResolveTypeReturn(ty, expr);
 3946        }
 03947        if (r == null) {
 03948          reporter.Error(MessageSource.Resolver, expr.tok, "member '{0}' does not exist in type '{1}' or cannot be part 
 03949        }
 03950      }
 3951
 03952      if (r == null) {
 3953        // an error has been reported above; we won't fill in .ResolvedExpression, but we still must fill in .Type
 03954        expr.Type = new InferredTypeProxy();
 03955      } else {
 03956        expr.ResolvedExpression = r;
 03957        expr.Type = r.Type;
 03958      }
 03959      return null;
 03960    }
 3961
 939883962    internal Resolver_IdentifierExpr CreateResolver_IdentifierExpr(IToken tok, string name, List<Type> optTypeArguments,
 3963      Contract.Requires(tok != null);
 3964      Contract.Requires(name != null);
 3965      Contract.Requires(decl != null);
 3966      Contract.Ensures(Contract.Result<Resolver_IdentifierExpr>() != null);
 3967
 1879763968      if (!moduleInfo.IsAbstract) {
 939883969        if (decl is ModuleDecl md && md.Signature.IsAbstract) {
 03970          reporter.Error(MessageSource.Resolver, tok, "a compiled module is not allowed to use an abstract module ({0})"
 03971        }
 939883972      }
 939883973      var n = optTypeArguments == null ? 0 : optTypeArguments.Count;
 1168563974      if (optTypeArguments != null) {
 3975        // type arguments were supplied; they must be equal in number to those expected
 228683976        if (n != decl.TypeArgs.Count) {
 03977          reporter.Error(MessageSource.Resolver, tok, "Wrong number of type arguments ({0} instead of {1}) passed to {2}
 03978        }
 228683979      }
 939883980      List<Type> tpArgs = new List<Type>();
 3052883981      for (int i = 0; i < decl.TypeArgs.Count; i++) {
 391043982        tpArgs.Add(i < n ? optTypeArguments[i] : new InferredTypeProxy());
 391043983      }
 939883984      return new Resolver_IdentifierExpr(tok, decl, tpArgs);
 939883985    }
 3986
 1230003987    public void ResolveStatement(Statement stmt, ResolutionContext resolutionContext) {
 3988      Contract.Requires(stmt != null);
 3989      Contract.Requires(resolutionContext != null);
 1293073990      if (stmt is ICanResolve canResolve) {
 63073991        canResolve.Resolve(this, resolutionContext);
 63073992        return;
 3993      }
 2330513994      if (!(stmt is ForallStmt || stmt is ForLoopStmt)) {  // "forall" and "for" statements do their own attribute resol
 1163583995        ResolveAttributes(stmt, resolutionContext);
 1163583996      }
 1178513997      if (stmt is PredicateStmt) {
 11583998        PredicateStmt s = (PredicateStmt)stmt;
 11583999        var assertStmt = stmt as AssertStmt;
 11584000        if (assertStmt != null && assertStmt.Label != null) {
 04001          if (DominatingStatementLabels.Find(assertStmt.Label.Name) != null) {
 04002            reporter.Error(MessageSource.Resolver, assertStmt.Label.Tok, "assert label shadows a dominating label");
 04003          } else {
 04004            var rr = DominatingStatementLabels.Push(assertStmt.Label.Name, assertStmt.Label);
 04005            Contract.Assert(rr == Scope<Label>.PushResult.Success);  // since we just checked for duplicates, we expect 
 04006          }
 04007        }
 4008
 11584009        if (assertStmt != null && Attributes.Find(assertStmt.Attributes, "only") is UserSuppliedAttributes attribute) {
 04010          reporter.Warning(MessageSource.Verifier, ResolutionErrors.ErrorId.r_assert_only_assumes_others.ToString(), att
 04011            "Assertion with {:only} temporarily transforms other assertions into assumptions");
 04012          if (attribute.Args.Count >= 1
 04013              && attribute.Args[0] is LiteralExpr { Value: string value }
 04014              && value != "before" && value != "after") {
 04015            reporter.Warning(MessageSource.Verifier, ResolutionErrors.ErrorId.r_assert_only_before_after.ToString(), att
 04016              "{:only} only accepts \"before\" or \"after\" as an optional argument");
 04017          }
 04018        }
 11584019        ResolveExpression(s.Expr, resolutionContext);
 11584020        Contract.Assert(s.Expr.Type != null);  // follows from postcondition of ResolveExpression
 11584021        ConstrainTypeExprBool(s.Expr, "condition is expected to be of type bool, but is {0}");
 11584022        if (assertStmt != null && assertStmt.Proof != null) {
 4023          // clear the labels for the duration of checking the proof body, because break statements are not allowed to l
 04024          var prevLblStmts = enclosingStatementLabels;
 04025          var prevLoopStack = loopStack;
 04026          enclosingStatementLabels = new Scope<Statement>(Options);
 04027          loopStack = new List<Statement>();
 04028          ResolveStatement(assertStmt.Proof, resolutionContext);
 04029          enclosingStatementLabels = prevLblStmts;
 04030          loopStack = prevLoopStack;
 04031        }
 11584032        var expectStmt = stmt as ExpectStmt;
 17374033        if (expectStmt != null) {
 9064034          if (expectStmt.Message == null) {
 3274035            expectStmt.Message = new StringLiteralExpr(s.Tok, "expectation violation", false);
 3274036          }
 5794037          ResolveExpression(expectStmt.Message, resolutionContext);
 5794038          Contract.Assert(expectStmt.Message.Type != null);  // follows from postcondition of ResolveExpression
 5794039        }
 4040
 1174424041      } else if (stmt is PrintStmt) {
 7494042        var s = (PrintStmt)stmt;
 889594043        s.Args.Iter(e => ResolveExpression(e, resolutionContext));
 4044
 1155354045      } else if (stmt is RevealStmt) {
 04046        var s = (RevealStmt)stmt;
 04047        foreach (var expr in s.Exprs) {
 04048          var name = RevealStmt.SingleName(expr);
 04049          var labeledAssert = name == null ? null : DominatingStatementLabels.Find(name) as AssertLabel;
 04050          if (labeledAssert != null) {
 04051            s.LabeledAsserts.Add(labeledAssert);
 04052          } else {
 04053            var revealResolutionContext = resolutionContext with { InReveal = true };
 04054            if (expr is ApplySuffix) {
 04055              var e = (ApplySuffix)expr;
 04056              var methodCallInfo = ResolveApplySuffix(e, revealResolutionContext, true);
 04057              if (methodCallInfo == null) {
 04058                reporter.Error(MessageSource.Resolver, expr.tok, "expression has no reveal lemma");
 04059              } else if (methodCallInfo.Callee.Member is TwoStateLemma && !revealResolutionContext.IsTwoState) {
 04060                reporter.Error(MessageSource.Resolver, methodCallInfo.Tok, "a two-state function can only be revealed in
 04061              } else if (methodCallInfo.Callee.AtLabel != null) {
 04062                Contract.Assert(methodCallInfo.Callee.Member is TwoStateLemma);
 04063                reporter.Error(MessageSource.Resolver, methodCallInfo.Tok, "to reveal a two-state function, do not list 
 04064              } else {
 04065                var call = new CallStmt(s.RangeToken, new List<Expression>(), methodCallInfo.Callee, methodCallInfo.Actu
 04066                s.ResolvedStatements.Add(call);
 04067              }
 04068            } else if (expr is NameSegment or ExprDotName) {
 04069              if (expr is NameSegment) {
 04070                ResolveNameSegment((NameSegment)expr, true, null, revealResolutionContext, true);
 04071              } else {
 04072                ResolveDotSuffix((ExprDotName)expr, true, null, revealResolutionContext, true);
 04073              }
 04074              MemberSelectExpr callee = (MemberSelectExpr)((ConcreteSyntaxExpression)expr).ResolvedExpression;
 04075              if (callee == null) {
 04076              } else if (callee.Member is Lemma or TwoStateLemma && Attributes.Contains(callee.Member.Attributes, "axiom
 4077                //The revealed member is a function
 04078                reporter.Error(MessageSource.Resolver, callee.tok, "to reveal a function ({0}), append parentheses", cal
 04079              } else {
 04080                var call = new CallStmt(s.RangeToken, new List<Expression>(), callee, new List<ActualBinding>(), expr.to
 04081                s.ResolvedStatements.Add(call);
 04082              }
 04083            } else {
 04084              ResolveExpression(expr, revealResolutionContext);
 04085            }
 04086          }
 04087        }
 04088        foreach (var a in s.ResolvedStatements) {
 04089          ResolveStatement(a, resolutionContext);
 04090        }
 1148864091      } else if (stmt is BreakStmt) {
 1004092        var s = (BreakStmt)stmt;
 1004093        if (s.TargetLabel != null) {
 04094          Statement target = enclosingStatementLabels.Find(s.TargetLabel.val);
 04095          if (target == null) {
 04096            reporter.Error(MessageSource.Resolver, s.TargetLabel, $"{s.Kind} label is undefined or not in scope: {s.Targ
 04097          } else if (s.IsContinue && !(target is LoopStmt)) {
 04098            reporter.Error(MessageSource.Resolver, s.TargetLabel, $"continue label must designate a loop: {s.TargetLabel
 04099          } else {
 04100            s.TargetStmt = target;
 04101          }
 1004102        } else {
 1004103          Contract.Assert(1 <= s.BreakAndContinueCount); // follows from BreakStmt class invariant and the guard for thi
 1004104          var jumpStmt = s.BreakAndContinueCount == 1 ?
 1004105            $"a non-labeled '{s.Kind}' statement" :
 1004106            $"a '{Util.Repeat(s.BreakAndContinueCount - 1, "break ")}{s.Kind}' statement";
 1004107          if (loopStack.Count == 0) {
 04108            reporter.Error(MessageSource.Resolver, s, $"{jumpStmt} is allowed only in loops");
 1004109          } else if (loopStack.Count < s.BreakAndContinueCount) {
 04110            reporter.Error(MessageSource.Resolver, s,
 04111              $"{jumpStmt} is allowed only in contexts with {s.BreakAndContinueCount} enclosing loops, but the current c
 1004112          } else {
 1004113            Statement target = loopStack[loopStack.Count - s.BreakAndContinueCount];
 1904114            if (target.Labels == null) {
 4115              // make sure there is a label, because the compiler and translator will want to see a unique ID
 904116              target.Labels = new LList<Label>(new Label(target.Tok, null), null);
 904117            }
 1004118            s.TargetStmt = target;
 1004119          }
 1004120        }
 4121
 1181304122      } else if (stmt is ProduceStmt) {
 33444123        var kind = stmt is YieldStmt ? "yield" : "return";
 33444124        if (stmt is YieldStmt && !(resolutionContext.CodeContext is IteratorDecl)) {
 04125          reporter.Error(MessageSource.Resolver, stmt, "yield statement is allowed only in iterators");
 33444126        } else if (stmt is ReturnStmt && !(resolutionContext.CodeContext is Method)) {
 04127          reporter.Error(MessageSource.Resolver, stmt, "return statement is allowed only in method");
 33444128        } else if (resolutionContext.InFirstPhaseConstructor) {
 04129          reporter.Error(MessageSource.Resolver, stmt, "return statement is not allowed before 'new;' in a constructor")
 04130        }
 33444131        var s = (ProduceStmt)stmt;
 59384132        if (s.Rhss != null) {
 25944133          var cmc = resolutionContext.CodeContext as IMethodCodeContext;
 25944134          if (cmc == null) {
 4135            // an error has already been reported above
 25944136          } else if (cmc.Outs.Count != s.Rhss.Count) {
 04137            reporter.Error(MessageSource.Resolver, s, "number of {2} parameters does not match declaration (found {0}, e
 25944138          } else {
 25944139            Contract.Assert(s.Rhss.Count > 0);
 4140            // Create a hidden update statement using the out-parameter formals, resolve the RHS, and check that the RHS
 25944141            List<Expression> formals = new List<Expression>();
 183904142            foreach (Formal f in cmc.Outs) {
 4143              Expression produceLhs;
 70724144              if (stmt is ReturnStmt) {
 35364145                var ident = new ImplicitIdentifierExpr(f.tok, f.Name);
 4146                // resolve it here to avoid capture into more closely declared local variables
 35364147                ident.Var = f;
 35364148                ident.Type = ident.Var.Type;
 35364149                Contract.Assert(f.Type != null);
 35364150                produceLhs = ident;
 35364151              } else {
 04152                var yieldIdent = new MemberSelectExpr(f.tok, new ImplicitThisExpr(f.tok), f.Name);
 04153                ResolveExpression(yieldIdent, resolutionContext);
 04154                produceLhs = yieldIdent;
 04155              }
 35364156              formals.Add(produceLhs);
 35364157            }
 25944158            s.HiddenUpdate = new UpdateStmt(s.RangeToken, formals, s.Rhss, true);
 4159            // resolving the update statement will check for return/yield statement specifics.
 25944160            ResolveStatement(s.HiddenUpdate, resolutionContext);
 25944161          }
 33444162        } else {// this is a regular return/yield statement.
 7504163          s.HiddenUpdate = null;
 7504164        }
 1635604165      } else if (stmt is VarDeclStmt) {
 488744166        var s = (VarDeclStmt)stmt;
 4167        // We have four cases.
 488744168        Contract.Assert(s.Update == null || s.Update is AssignSuchThatStmt || s.Update is UpdateStmt || s.Update is Assi
 4169        // 0.  There is no .Update.  This is easy, we will just resolve the locals.
 4170        // 1.  The .Update is an AssignSuchThatStmt.  This is also straightforward:  first
 4171        //     resolve the locals, which adds them to the scope, and then resolve the .Update.
 4172        // 2.  The .Update is an UpdateStmt, which, resolved, means either a CallStmt or a bunch
 4173        //     of parallel AssignStmt's.  Here, the right-hand sides should be resolved before
 4174        //     the local variables have been added to the scope, but the left-hand sides should
 4175        //     resolve to the newly introduced variables.
 4176        // 3.  The .Update is a ":-" statement, for which resolution does two steps:
 4177        //     First, desugar, then run the regular resolution on the desugared AST.
 4178        // To accommodate these options, we first reach into the UpdateStmt, if any, to resolve
 4179        // the left-hand sides of the UpdateStmt.  This will have the effect of shielding them
 4180        // from a subsequent resolution (since expression resolution will do nothing if the .Type
 4181        // field is already assigned.
 4182        // Alright, so it is:
 4183
 4184        // Resolve the types of the locals
 2987734185        foreach (var local in s.Locals) {
 507174186          int prevErrorCount = reporter.Count(ErrorLevel.Error);
 507174187          ResolveType(local.Tok, local.OptionalType, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 1014344188          if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 507174189            local.type = local.OptionalType;
 507174190          } else {
 04191            local.type = new InferredTypeProxy();
 04192          }
 507174193        }
 4194        // Resolve the UpdateStmt, if any
 977484195        if (s.Update is UpdateStmt) {
 488744196          var upd = (UpdateStmt)s.Update;
 4197          // resolve the LHS
 488744198          Contract.Assert(upd.Lhss.Count == s.Locals.Count);
 2498994199          for (int i = 0; i < upd.Lhss.Count; i++) {
 507174200            var local = s.Locals[i];
 507174201            var lhs = (IdentifierExpr)upd.Lhss[i];  // the LHS in this case will be an IdentifierExpr, because that's ho
 507174202            Contract.Assert(lhs.Type == null);  // not yet resolved
 507174203            lhs.Var = local;
 507174204            lhs.Type = local.Type;
 507174205          }
 4206          // resolve the whole thing
 488744207          s.Update.Resolve(this, resolutionContext);
 488744208        }
 4209
 488744210        if (s.Update is AssignOrReturnStmt) {
 04211          var assignOrRet = (AssignOrReturnStmt)s.Update;
 4212          // resolve the LHS
 04213          Contract.Assert(assignOrRet.Lhss.Count == s.Locals.Count);
 04214          for (int i = 0; i < s.Locals.Count; i++) {
 04215            var local = s.Locals[i];
 04216            var lhs = (IdentifierExpr)assignOrRet
 04217              .Lhss[i]; // the LHS in this case will be an IdentifierExpr, because that's how the parser creates the Var
 04218            Contract.Assert(lhs.Type == null); // not yet resolved
 04219            lhs.Var = local;
 04220            lhs.Type = local.Type;
 04221          }
 4222
 4223          // resolve the whole thing
 04224          assignOrRet.Resolve(this, resolutionContext);
 04225        }
 4226        // Add the locals to the scope
 2987734227        foreach (var local in s.Locals) {
 507174228          ScopePushAndReport(scope, local, "local-variable");
 507174229        }
 4230        // With the new locals in scope, it's now time to resolve the attributes on all the locals
 2987734231        foreach (var local in s.Locals) {
 507174232          ResolveAttributes(local, resolutionContext);
 507174233        }
 4234        // Resolve the AssignSuchThatStmt, if any
 488744235        if (s.Update is AssignSuchThatStmt assignSuchThatStmt) {
 04236          assignSuchThatStmt.Resolve(this, resolutionContext);
 04237        }
 1113424238      } else if (stmt is VarDeclPattern) {
 04239        VarDeclPattern s = (VarDeclPattern)stmt;
 04240        foreach (var local in s.LocalVars) {
 04241          int prevErrorCount = reporter.Count(ErrorLevel.Error);
 04242          ResolveType(local.Tok, local.OptionalType, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 04243          if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 04244            local.type = local.OptionalType;
 04245          } else {
 04246            local.type = new InferredTypeProxy();
 04247          }
 04248        }
 04249        ResolveExpression(s.RHS, resolutionContext);
 04250        ResolveCasePattern(s.LHS, s.RHS.Type, resolutionContext);
 4251        // Check for duplicate names now, because not until after resolving the case pattern do we know if identifiers i
 04252        var c = 0;
 04253        foreach (var bv in s.LHS.Vars) {
 04254          ScopePushAndReport(scope, bv, "local_variable");
 04255          c++;
 04256        }
 04257        if (c == 0) {
 4258          // Every identifier-looking thing in the pattern resolved to a constructor; that is, this LHS is a constant li
 04259          reporter.Error(MessageSource.Resolver, s.LHS.tok, "LHS is a constant literal; to be legal, it must introduce a
 04260        }
 1180374261      } else if (stmt is AssignStmt) {
 555694262        AssignStmt s = (AssignStmt)stmt;
 555694263        int prevErrorCount = reporter.Count(ErrorLevel.Error);
 555694264        ResolveExpression(s.Lhs, resolutionContext);  // allow ghosts for now, tighted up below
 555694265        bool lhsResolvedSuccessfully = reporter.Count(ErrorLevel.Error) == prevErrorCount;
 555694266        Contract.Assert(s.Lhs.Type != null);  // follows from postcondition of ResolveExpression
 4267        // check that LHS denotes a mutable variable or a field
 555694268        var lhs = s.Lhs.Resolved;
 1095084269        if (lhs is IdentifierExpr) {
 539394270          IVariable var = ((IdentifierExpr)lhs).Var;
 539394271          if (var == null) {
 4272            // the LHS didn't resolve correctly; some error would already have been reported
 539394273          } else {
 539394274            CheckIsLvalue(lhs, resolutionContext);
 539394275          }
 555694276        } else if (lhs is MemberSelectExpr) {
 04277          var fse = (MemberSelectExpr)lhs;
 04278          if (fse.Member != null) {  // otherwise, an error was reported above
 04279            CheckIsLvalue(fse, resolutionContext);
 04280          }
 32604281        } else if (lhs is SeqSelectExpr) {
 16304282          var slhs = (SeqSelectExpr)lhs;
 4283          // LHS is fine, provided the "sequence" is really an array
 32604284          if (lhsResolvedSuccessfully) {
 16304285            Contract.Assert(slhs.Seq.Type != null);
 16304286            CheckIsLvalue(slhs, resolutionContext);
 16304287          }
 16304288        } else if (lhs is MultiSelectExpr) {
 04289          CheckIsLvalue(lhs, resolutionContext);
 04290        } else {
 04291          CheckIsLvalue(lhs, resolutionContext);
 04292        }
 555694293        Type lhsType = s.Lhs.Type;
 1076384294        if (s.Rhs is ExprRhs) {
 520694295          ExprRhs rr = (ExprRhs)s.Rhs;
 520694296          ResolveExpression(rr.Expr, resolutionContext);
 520694297          Contract.Assert(rr.Expr.Type != null);  // follows from postcondition of ResolveExpression
 4298
 556054299          if (s.Lhs is ImplicitIdentifierExpr { Var: Formal { InParam: false } }) {
 35364300            AddAssignableConstraint(stmt.Tok, lhsType, rr.Expr.Type, "Method return value mismatch (expected {0}, got {1
 520694301          } else {
 485334302            AddAssignableConstraint(stmt.Tok, lhsType, rr.Expr.Type, "RHS (of type {1}) not assignable to LHS (of type {
 485334303          }
 590694304        } else if (s.Rhs is TypeRhs) {
 35004305          TypeRhs rr = (TypeRhs)s.Rhs;
 35004306          Type t = ResolveTypeRhs(rr, stmt, resolutionContext);
 35004307          AddAssignableConstraint(stmt.Tok, lhsType, t, "type {1} is not assignable to LHS (of type {0})");
 35004308        } else if (s.Rhs is HavocRhs) {
 4309          // nothing else to do
 04310        } else {
 04311          Contract.Assert(false); throw new cce.UnreachableException();  // unexpected RHS
 4312        }
 4313
 659394314      } else if (stmt is CallStmt) {
 34714315        CallStmt s = (CallStmt)stmt;
 34714316        ResolveCallStmt(s, resolutionContext, null);
 4317
 85884318      } else if (stmt is BlockStmt) {
 16894319        var s = (BlockStmt)stmt;
 16894320        scope.PushMarker();
 16894321        ResolveBlockStatement(s, resolutionContext);
 16894322        scope.PopMarker();
 4323
 44574324      } else if (stmt is IfStmt) {
 10294325        IfStmt s = (IfStmt)stmt;
 20584326        if (s.Guard != null) {
 10294327          ResolveExpression(s.Guard, resolutionContext);
 10294328          Contract.Assert(s.Guard.Type != null);  // follows from postcondition of ResolveExpression
 10294329          ConstrainTypeExprBool(s.Guard, "condition is expected to be of type bool, but is {0}");
 10294330        }
 4331
 10294332        scope.PushMarker();
 10294333        if (s.IsBindingGuard) {
 04334          var exists = (ExistsExpr)s.Guard;
 04335          foreach (var v in exists.BoundVars) {
 04336            ScopePushAndReport(scope, v, "bound-variable");
 04337          }
 04338        }
 10294339        DominatingStatementLabels.PushMarker();
 10294340        ResolveBlockStatement(s.Thn, resolutionContext);
 10294341        DominatingStatementLabels.PopMarker();
 10294342        scope.PopMarker();
 4343
 16834344        if (s.Els != null) {
 6544345          DominatingStatementLabels.PushMarker();
 6544346          ResolveStatement(s.Els, resolutionContext);
 6544347          DominatingStatementLabels.PopMarker();
 6544348        }
 4349
 17394350      } else if (stmt is AlternativeStmt) {
 04351        var s = (AlternativeStmt)stmt;
 04352        ResolveAlternatives(s.Alternatives, null, resolutionContext);
 4353
 14204354      } else if (stmt is OneBodyLoopStmt) {
 7104355        var s = (OneBodyLoopStmt)stmt;
 10854356        if (s is WhileStmt whileS && whileS.Guard != null) {
 3754357          ResolveExpression(whileS.Guard, resolutionContext);
 3754358          Contract.Assert(whileS.Guard.Type != null);  // follows from postcondition of ResolveExpression
 3754359          ConstrainTypeExprBool(whileS.Guard, "condition is expected to be of type bool, but is {0}");
 10454360        } else if (s is ForLoopStmt forS) {
 3354361          var loopIndex = forS.LoopIndex;
 3354362          int prevErrorCount = reporter.Count(ErrorLevel.Error);
 3354363          ResolveType(loopIndex.Tok, loopIndex.Type, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 3354364          var err = new TypeConstraint.ErrorMsgWithToken(loopIndex.Tok, "index variable is expected to be of an integer 
 3354365          ConstrainToIntegerType(loopIndex.Tok, loopIndex.Type, false, err);
 4366
 3354367          ResolveExpression(forS.Start, resolutionContext);
 3354368          AddAssignableConstraint(forS.Start.tok, forS.LoopIndex.Type, forS.Start.Type, "lower bound (of type {1}) not a
 6704369          if (forS.End != null) {
 3354370            ResolveExpression(forS.End, resolutionContext);
 3354371            AddAssignableConstraint(forS.End.tok, forS.LoopIndex.Type, forS.End.Type, "upper bound (of type {1}) not ass
 3354372            if (forS.Decreases.Expressions.Count != 0) {
 04373              reporter.Error(MessageSource.Resolver, forS.Decreases.Expressions[0].tok,
 04374                "a 'for' loop is allowed an explicit 'decreases' clause only if the end-expression is '*'");
 04375            }
 3354376          } else if (forS.Decreases.Expressions.Count == 0 && !resolutionContext.CodeContext.AllowsNontermination) {
 4377            // note, the following error message is also emitted elsewhere (if the loop bears a "decreases *")
 04378            reporter.Error(MessageSource.Resolver, forS.Tok,
 04379              "a possibly infinite loop is allowed only if the enclosing method is declared (with 'decreases *') to be p
 04380              " (or you can add a 'decreases' clause to this 'for' loop if you want to prove that it does indeed termina
 04381          }
 4382
 4383          // Create a new scope, add the local to the scope, and resolve the attributes
 3354384          scope.PushMarker();
 3354385          ScopePushAndReport(scope, loopIndex, "index-variable");
 3354386          ResolveAttributes(s, resolutionContext);
 3354387        }
 4388
 7104389        ResolveLoopSpecificationComponents(s.Invariants, s.Decreases, s.Mod, resolutionContext);
 4390
 14204391        if (s.Body != null) {
 7104392          loopStack.Add(s);  // push
 7104393          DominatingStatementLabels.PushMarker();
 7104394          ResolveStatement(s.Body, resolutionContext);
 7104395          DominatingStatementLabels.PopMarker();
 7104396          loopStack.RemoveAt(loopStack.Count - 1);  // pop
 7104397        }
 4398
 10454399        if (s is ForLoopStmt) {
 3354400          scope.PopMarker();
 3354401        }
 4402
 7104403      } else if (stmt is AlternativeLoopStmt) {
 04404        var s = (AlternativeLoopStmt)stmt;
 04405        ResolveAlternatives(s.Alternatives, s, resolutionContext);
 04406        ResolveLoopSpecificationComponents(s.Invariants, s.Decreases, s.Mod, resolutionContext);
 4407
 04408      } else if (stmt is ForallStmt) {
 04409        var s = (ForallStmt)stmt;
 4410
 04411        int prevErrorCount = reporter.Count(ErrorLevel.Error);
 04412        scope.PushMarker();
 04413        foreach (BoundVar v in s.BoundVars) {
 04414          ScopePushAndReport(scope, v, "local-variable");
 04415          ResolveType(v.tok, v.Type, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 04416        }
 04417        ResolveExpression(s.Range, resolutionContext);
 04418        Contract.Assert(s.Range.Type != null);  // follows from postcondition of ResolveExpression
 04419        ConstrainTypeExprBool(s.Range, "range restriction in forall statement must be of type bool (instead got {0})");
 04420        foreach (var ens in s.Ens) {
 04421          ResolveExpression(ens.E, resolutionContext);
 04422          Contract.Assert(ens.E.Type != null);  // follows from postcondition of ResolveExpression
 04423          ConstrainTypeExprBool(ens.E, "ensures condition is expected to be of type bool, but is {0}");
 04424        }
 4425        // Since the range and postconditions are more likely to infer the types of the bound variables, resolve them
 4426        // first (above) and only then resolve the attributes (below).
 04427        ResolveAttributes(s, resolutionContext);
 4428
 04429        if (s.Body != null) {
 4430          // clear the labels for the duration of checking the body, because break statements are not allowed to leave a
 04431          var prevLblStmts = enclosingStatementLabels;
 04432          var prevLoopStack = loopStack;
 04433          enclosingStatementLabels = new Scope<Statement>(Options);
 04434          loopStack = new List<Statement>();
 04435          ResolveStatement(s.Body, resolutionContext);
 04436          enclosingStatementLabels = prevLblStmts;
 04437          loopStack = prevLoopStack;
 04438        }
 04439        scope.PopMarker();
 4440
 04441        if (prevErrorCount == reporter.Count(ErrorLevel.Error)) {
 4442          // determine the Kind and run some additional checks on the body
 04443          if (s.Ens.Count != 0) {
 4444            // The only supported kind with ensures clauses is Proof.
 04445            s.Kind = ForallStmt.BodyKind.Proof;
 04446          } else {
 4447            // There are three special cases:
 4448            // * Assign, which is the only kind of the forall statement that allows a heap update.
 4449            // * Call, which is a single call statement with no side effects or output parameters.
 4450            // * A single calc statement, which is a special case of Proof where the postcondition can be inferred.
 4451            // The effect of Assign and the postcondition of Call will be seen outside the forall
 4452            // statement.
 04453            Statement s0 = s.S0;
 04454            if (s0 is AssignStmt) {
 04455              s.Kind = ForallStmt.BodyKind.Assign;
 4456
 04457              var rhs = ((AssignStmt)s0).Rhs;
 04458              if (rhs is TypeRhs) {
 04459                reporter.Error(MessageSource.Resolver, rhs.Tok, "new allocation not supported in aggregate assignments")
 04460              }
 4461
 04462            } else if (s0 is CallStmt) {
 04463              s.Kind = ForallStmt.BodyKind.Call;
 04464              var call = (CallStmt)s.S0;
 04465              var method = call.Method;
 4466              // if the called method is not in the same module as the ForallCall stmt
 4467              // don't convert it to ForallExpression since the inlined called method's
 4468              // ensure clause might not be resolved correctly(test\dafny3\GenericSort.dfy)
 04469              if (method.EnclosingClass.EnclosingModuleDefinition != resolutionContext.CodeContext.EnclosingModule) {
 04470                s.CanConvert = false;
 04471              }
 4472              // Additional information (namely, the postcondition of the call) will be reported later. But it cannot be
 4473              // done yet, because the specification of the callee may not have been resolved yet.
 04474            } else if (s0 is CalcStmt) {
 04475              s.Kind = ForallStmt.BodyKind.Proof;
 4476              // add the conclusion of the calc as a free postcondition
 04477              var result = ((CalcStmt)s0).Result;
 04478              s.Ens.Add(new AttributedExpression(result));
 04479              reporter.Info(MessageSource.Resolver, s.Tok, "ensures " + Printer.ExprToString(Options, result));
 04480            } else {
 04481              s.Kind = ForallStmt.BodyKind.Proof;
 04482              if (s.Body is BlockStmt && ((BlockStmt)s.Body).Body.Count == 0) {
 4483                // an empty statement, so don't produce any warning
 04484              } else {
 04485                reporter.Warning(MessageSource.Resolver, ErrorRegistry.NoneId, s.Tok, "the conclusion of the body of thi
 04486              }
 04487            }
 04488          }
 4489
 04490          if (s.ForallExpressions != null) {
 04491            foreach (Expression expr in s.ForallExpressions) {
 04492              ResolveExpression(expr, resolutionContext);
 04493            }
 04494          }
 04495        }
 4496
 04497      } else if (stmt is ModifyStmt) {
 04498        var s = (ModifyStmt)stmt;
 04499        ResolveAttributes(s.Mod, resolutionContext);
 04500        foreach (FrameExpression fe in s.Mod.Expressions) {
 04501          ResolveFrameExpression(fe, FrameExpressionUse.Modifies, resolutionContext);
 04502        }
 04503        if (s.Body != null) {
 04504          ResolveBlockStatement(s.Body, resolutionContext);
 04505        }
 4506
 04507      } else if (stmt is CalcStmt) {
 04508        var prevErrorCount = reporter.Count(ErrorLevel.Error);
 04509        CalcStmt s = (CalcStmt)stmt;
 4510        // figure out s.Op
 04511        Contract.Assert(s.Op == null);  // it hasn't been set yet
 04512        if (s.UserSuppliedOp != null) {
 04513          s.Op = s.UserSuppliedOp;
 04514        } else {
 04515          s.Op = s.GetInferredDefaultOp() ?? CalcStmt.DefaultOp;
 04516          reporter.Info(MessageSource.Resolver, s.Tok, s.Op.ToString());
 04517        }
 4518
 04519        if (s.Lines.Count > 0) {
 04520          Type lineType = new InferredTypeProxy();
 04521          var e0 = s.Lines.First();
 04522          ResolveExpression(e0, resolutionContext);
 04523          Contract.Assert(e0.Type != null);  // follows from postcondition of ResolveExpression
 04524          var err = new TypeConstraint.ErrorMsgWithToken(e0.tok, "all lines in a calculation must have the same type (go
 04525          ConstrainSubtypeRelation(lineType, e0.Type, err);
 04526          for (int i = 1; i < s.Lines.Count; i++) {
 04527            var e1 = s.Lines[i];
 04528            ResolveExpression(e1, resolutionContext);
 04529            Contract.Assert(e1.Type != null);  // follows from postcondition of ResolveExpression
 4530            // reuse the error object if we're on the dummy line; this prevents a duplicate error message
 04531            if (i < s.Lines.Count - 1) {
 04532              err = new TypeConstraint.ErrorMsgWithToken(e1.tok, "all lines in a calculation must have the same type (go
 04533            }
 04534            ConstrainSubtypeRelation(lineType, e1.Type, err);
 04535            var step = (s.StepOps[i - 1] ?? s.Op).StepExpr(e0, e1); // Use custom line operator
 04536            ResolveExpression(step, resolutionContext);
 04537            s.Steps.Add(step);
 04538            e0 = e1;
 04539          }
 4540
 4541          // clear the labels for the duration of checking the hints, because break statements are not allowed to leave 
 04542          var prevLblStmts = enclosingStatementLabels;
 04543          var prevLoopStack = loopStack;
 04544          enclosingStatementLabels = new Scope<Statement>(Options);
 04545          loopStack = new List<Statement>();
 04546          foreach (var h in s.Hints) {
 04547            foreach (var oneHint in h.Body) {
 04548              DominatingStatementLabels.PushMarker();
 04549              ResolveStatement(oneHint, resolutionContext);
 04550              DominatingStatementLabels.PopMarker();
 04551            }
 04552          }
 04553          enclosingStatementLabels = prevLblStmts;
 04554          loopStack = prevLoopStack;
 4555
 04556        }
 04557        if (prevErrorCount == reporter.Count(ErrorLevel.Error) && s.Lines.Count > 0) {
 4558          // do not build Result from the lines if there were errors, as it might be ill-typed and produce unnecessary r
 04559          var resultOp = s.StepOps.Aggregate(s.Op, (op0, op1) => op1 == null ? op0 : op0.ResultOp(op1));
 04560          s.Result = resultOp.StepExpr(s.Lines.First(), s.Lines.Last());
 04561        } else {
 04562          s.Result = CalcStmt.DefaultOp.StepExpr(Expression.CreateIntLiteral(s.Tok, 0), Expression.CreateIntLiteral(s.To
 04563        }
 04564        ResolveExpression(s.Result, resolutionContext);
 04565        Contract.Assert(s.Result != null);
 04566        Contract.Assert(prevErrorCount != reporter.Count(ErrorLevel.Error) || s.Steps.Count == s.Hints.Count);
 4567
 04568      } else if (stmt is SkeletonStatement) {
 04569        var s = (SkeletonStatement)stmt;
 04570        reporter.Error(MessageSource.Resolver, s.Tok, "skeleton statements are allowed only in refining methods");
 4571        // nevertheless, resolve the underlying statement; hey, why not
 04572        if (s.S != null) {
 04573          ResolveStatement(s.S, resolutionContext);
 04574        }
 04575      } else {
 04576        Contract.Assert(false); throw new cce.UnreachableException();
 4577      }
 1230004578    }
 4579
 4580    private void ResolveLoopSpecificationComponents(List<AttributedExpression> invariants, Specification<Expression> dec
 7104581      Specification<FrameExpression> modifies, ResolutionContext resolutionContext) {
 4582      Contract.Requires(invariants != null);
 4583      Contract.Requires(decreases != null);
 4584      Contract.Requires(modifies != null);
 4585      Contract.Requires(resolutionContext != null);
 4586
 42604587      foreach (AttributedExpression inv in invariants) {
 7104588        ResolveAttributes(inv, resolutionContext);
 7104589        ResolveExpression(inv.E, resolutionContext);
 7104590        Contract.Assert(inv.E.Type != null);  // follows from postcondition of ResolveExpression
 7104591        ConstrainTypeExprBool(inv.E, "invariant is expected to be of type bool, but is {0}");
 7104592      }
 4593
 7104594      ResolveAttributes(decreases, resolutionContext);
 32554595      foreach (Expression e in decreases.Expressions) {
 3754596        ResolveExpression(e, resolutionContext);
 3754597        if (e is WildcardExpr && !resolutionContext.CodeContext.AllowsNontermination) {
 04598          reporter.Error(MessageSource.Resolver, e, "a possibly infinite loop is allowed only if the enclosing method is
 04599        }
 4600        // any type is fine
 3754601      }
 4602
 7104603      ResolveAttributes(modifies, resolutionContext);
 7104604      if (modifies.Expressions != null) {
 04605        foreach (FrameExpression fe in modifies.Expressions) {
 04606          ResolveFrameExpression(fe, FrameExpressionUse.Modifies, resolutionContext);
 04607        }
 04608      }
 7104609    }
 4610
 4611    /// <summary>
 4612    /// Resolves the default-valued expression for each formal in "formals".
 4613    /// Solves the resulting type constraints.
 4614    /// Assumes these are the only type constraints to be solved.
 4615    ///
 4616    /// Reports an error for any cyclic dependency among the default-value expressions of the formals.
 4617    /// </summary>
 26434618    public void ResolveParameterDefaultValues(List<Formal> formals, ResolutionContext resolutionContext) {
 4619      Contract.Requires(formals != null);
 4620      Contract.Requires(resolutionContext != null);
 4621
 26434622      Contract.Assume(AllTypeConstraints.Count == 0);
 4623
 4624      // Formal parameters have three ways to indicate how they are to be passed in:
 4625      //   * nameonly: the only way to give a specific argument value is to name the parameter
 4626      //   * positional only: these are nameless parameters (which are allowed only for datatype constructor parameters)
 4627      //   * either positional or by name: this is the most common parameter
 4628      // A parameter is either required or optional:
 4629      //   * required: a caller has to supply an argument
 4630      //   * optional: the parameter has a default value that is used if a caller omits passing a specific argument
 4631      //
 4632      // The syntax for giving a positional-only (i.e., nameless) parameter does not allow a default-value expression, s
 4633      // a positional-only parameter is always required.
 4634      //
 4635      // At a call site, positional arguments are not allowed to follow named arguments. Therefore, if "x" is
 4636      // a nameonly parameter, then there is no way to supply the parameters after "x" by position. Thus, any
 4637      // parameter that follows "x" must either be passed by name or have a default value. That is, if a later
 4638      // parameter does not have a default value, it is _effectively_ nameonly. We impose the rule that
 4639      //   * an effectively nameonly parameter must be declared as nameonly
 4640      //
 4641      // For a positional-only parameter "x", every parameter preceding "x" is _effectively_ required. We impose
 4642      // the rule that
 4643      //   * an effectively required parameter must not have a default-value expression
 26434644      var dependencies = new Graph<IVariable>();
 26434645      string nameOfMostRecentNameonlyParameter = null;
 26434646      var previousParametersWithDefaultValue = new HashSet<Formal>();
 223804647      foreach (var formal in formals) {
 48174648        if (!formal.HasName) {
 04649          foreach (var previousFormal in previousParametersWithDefaultValue) {
 04650            reporter.Error(MessageSource.Resolver, previousFormal.DefaultValue.tok,
 04651              $"because of a later nameless parameter, this default value is never used; remove it or name all subsequen
 04652          }
 04653          previousParametersWithDefaultValue.Clear();
 04654        }
 48174655        var d = formal.DefaultValue;
 48174656        if (d != null) {
 04657          ResolveExpression(d, resolutionContext);
 04658          AddAssignableConstraint(d.tok, formal.Type, d.Type, "default-value expression (of type '{1}') is not assignabl
 04659          foreach (var v in FreeVariables(d)) {
 04660            dependencies.AddEdge(formal, v);
 04661          }
 04662          previousParametersWithDefaultValue.Add(formal);
 48174663        } else if (nameOfMostRecentNameonlyParameter != null && !formal.IsNameOnly) {
 4664          // "formal" is preceded by a nameonly parameter, but itself is neither nameonly nor has a default value
 04665          reporter.Error(MessageSource.Resolver, formal.tok,
 04666            $"this parameter is effectively nameonly (because of the earlier nameonly parameter '{nameOfMostRecentNameon
 04667            "declare it as nameonly or give it a default-value expression");
 04668        }
 48174669        if (formal.IsNameOnly) {
 04670          nameOfMostRecentNameonlyParameter = formal.Name;
 04671        }
 48174672      }
 26434673      SolveAllTypeConstraints();
 4674
 79294675      foreach (var cycle in dependencies.AllCycles()) {
 04676        var cy = Util.Comma(" -> ", cycle, v => v.Name) + " -> " + cycle[0].Name;
 04677        reporter.Error(MessageSource.Resolver, cycle[0], $"default-value expressions for parameters contain a cycle: {cy
 04678      }
 26434679    }
 4680
 4681    /// <summary>
 4682    /// See ResolveTypeOption for a description of the option/defaultTypeArguments parameters.
 4683    /// </summary>
 1307744684    public void ResolveType(IToken tok, Type type, ResolutionContext resolutionContext, ResolveTypeOptionEnum eopt, List
 4685      Contract.Requires(tok != null);
 4686      Contract.Requires(type != null);
 4687      Contract.Requires(resolutionContext != null);
 4688      Contract.Requires(eopt != ResolveTypeOptionEnum.AllowPrefixExtend);
 1307744689      ResolveType(tok, type, resolutionContext, new ResolveTypeOption(eopt), defaultTypeArguments);
 1307744690    }
 4691
 8144692    public void ResolveType(IToken tok, Type type, ICodeContext topLevelContext, ResolveTypeOptionEnum eopt, List<TypePa
 8144693      ResolveType(tok, type, ResolutionContext.FromCodeContext(topLevelContext), eopt, defaultTypeArguments);
 8144694    }
 4695
 71584696    public void ResolveType(IToken tok, Type type, ICodeContext topLevelContext, ResolveTypeOption option, List<TypePara
 71584697      ResolveType(tok, type, ResolutionContext.FromCodeContext(topLevelContext), option, defaultTypeArguments);
 71584698    }
 4699
 2020214700    public void ResolveType(IToken tok, Type type, ResolutionContext resolutionContext, ResolveTypeOption option, List<T
 4701      Contract.Requires(tok != null);
 4702      Contract.Requires(type != null);
 4703      Contract.Requires(resolutionContext != null);
 4704      Contract.Requires(option != null);
 4705      Contract.Requires((option.Opt == ResolveTypeOptionEnum.DontInfer || option.Opt == ResolveTypeOptionEnum.InferTypeP
 2020214706      var r = ResolveTypeLenient(tok, type, resolutionContext, option, defaultTypeArguments, false);
 2020214707      Contract.Assert(r == null);
 2020214708    }
 4709
 4710    public class ResolveTypeReturn {
 4711      public readonly Type ReplacementType;
 4712      public readonly ExprDotName LastComponent;
 04713      public ResolveTypeReturn(Type replacementType, ExprDotName lastComponent) {
 4714        Contract.Requires(replacementType != null);
 4715        Contract.Requires(lastComponent != null);
 04716        ReplacementType = replacementType;
 04717        LastComponent = lastComponent;
 04718      }
 4719    }
 4720    /// <summary>
 4721    /// See ResolveTypeOption for a description of the option/defaultTypeArguments parameters.
 4722    /// One more thing:  if "allowDanglingDotName" is true, then if the resolution would have produced
 4723    ///   an error message that could have been avoided if "type" denoted an identifier sequence one
 4724    ///   shorter, then return an unresolved replacement type where the identifier sequence is one
 4725    ///   shorter.  (In all other cases, the method returns null.)
 4726    /// </summary>
 2020214727    public ResolveTypeReturn ResolveTypeLenient(IToken tok, Type type, ResolutionContext resolutionContext, ResolveTypeO
 4728      Contract.Requires(tok != null);
 4729      Contract.Requires(type != null);
 4730      Contract.Requires(resolutionContext != null);
 4731      Contract.Requires((option.Opt == ResolveTypeOptionEnum.DontInfer || option.Opt == ResolveTypeOptionEnum.InferTypeP
 2020214732      if (type is BitvectorType) {
 04733        var t = (BitvectorType)type;
 4734        // nothing to resolve, but record the fact that this bitvector width is in use
 04735        builtIns.Bitwidths.Add(t.Width);
 2838404736      } else if (type is BasicType) {
 4737        // nothing to resolve
 2085434738      } else if (type is MapType) {
 65224739        var mt = (MapType)type;
 65224740        var errorCount = reporter.Count(ErrorLevel.Error);
 4741        int typeArgumentCount;
 130444742        if (mt.HasTypeArg()) {
 65224743          ResolveType(tok, mt.Domain, resolutionContext, option, defaultTypeArguments);
 65224744          ResolveType(tok, mt.Range, resolutionContext, option, defaultTypeArguments);
 65224745          typeArgumentCount = 2;
 65224746        } else if (option.Opt == ResolveTypeOptionEnum.DontInfer) {
 04747          mt.SetTypeArgs(new InferredTypeProxy(), new InferredTypeProxy());
 04748          typeArgumentCount = 0;
 04749        } else {
 04750          var inferredTypeArgs = new List<Type>();
 04751          FillInTypeArguments(tok, 2, inferredTypeArgs, defaultTypeArguments, option);
 04752          Contract.Assert(inferredTypeArgs.Count <= 2);
 04753          if (inferredTypeArgs.Count == 1) {
 04754            mt.SetTypeArgs(inferredTypeArgs[0], new InferredTypeProxy());
 04755            typeArgumentCount = 1;
 04756          } else if (inferredTypeArgs.Count == 2) {
 04757            mt.SetTypeArgs(inferredTypeArgs[0], inferredTypeArgs[1]);
 04758            typeArgumentCount = 2;
 04759          } else {
 04760            mt.SetTypeArgs(new InferredTypeProxy(), new InferredTypeProxy());
 04761            typeArgumentCount = 0;
 04762          }
 04763        }
 4764        // defaults and auto have been applied; check if we now have the right number of arguments
 65224765        if (2 != typeArgumentCount) {
 04766          reporter.Error(MessageSource.Resolver, tok, "Wrong number of type arguments ({0} instead of 2) passed to type:
 04767        }
 1325914768      } else if (type is CollectionType) {
 123894769        var t = (CollectionType)type;
 123894770        var errorCount = reporter.Count(ErrorLevel.Error);
 243304771        if (t.HasTypeArg()) {
 119414772          ResolveType(tok, t.Arg, resolutionContext, option, defaultTypeArguments);
 128374773        } else if (option.Opt != ResolveTypeOptionEnum.DontInfer) {
 4484774          var inferredTypeArgs = new List<Type>();
 4484775          FillInTypeArguments(tok, 1, inferredTypeArgs, defaultTypeArguments, option);
 8964776          if (inferredTypeArgs.Count != 0) {
 4484777            Contract.Assert(inferredTypeArgs.Count == 1);
 4484778            t.SetTypeArg(inferredTypeArgs[0]);
 4484779          }
 4484780        }
 123894781        if (!t.HasTypeArg()) {
 4782          // defaults and auto have been applied; check if we now have the right number of arguments
 04783          reporter.Error(MessageSource.Resolver, tok, "Wrong number of type arguments (0 instead of 1) passed to type: {
 4784          // add a proxy type, to make sure that CollectionType will have have a non-null Arg
 04785          t.SetTypeArg(new InferredTypeProxy());
 04786        }
 4787
 2090494788      } else if (type is UserDefinedType) {
 953694789        var t = (UserDefinedType)type;
 962264790        if (t.ResolvedClass != null) {
 4791          // Apparently, this type has already been resolved
 8574792          return null;
 4793        }
 945124794        var prevErrorCount = reporter.Count(ErrorLevel.Error);
 945124795        if (t.NamePath is ExprDotName) {
 04796          var ret = ResolveDotSuffix_Type((ExprDotName)t.NamePath, resolutionContext, allowDanglingDotName, option, defa
 04797          if (ret != null) {
 04798            return ret;
 4799          }
 945124800        } else {
 945124801          var s = (NameSegment)t.NamePath;
 945124802          ResolveNameSegment_Type(s, resolutionContext, option, defaultTypeArguments);
 945124803        }
 1890244804        if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 945124805          var r = t.NamePath.Resolved as Resolver_IdentifierExpr;
 945124806          if (r == null || !(r.Type is Resolver_IdentifierExpr.ResolverType_Type)) {
 04807            reporter.Error(MessageSource.Resolver, t.tok, "expected type");
 1890244808          } else if (r.Type is Resolver_IdentifierExpr.ResolverType_Type) {
 945124809            var d = r.Decl;
 945124810            if (d is AbstractTypeDecl) {
 4811              // resolve like a type parameter, and it may have type parameters if it's an abstract type
 04812              t.ResolvedClass = d;  // Store the decl, so the compiler will generate the fully qualified name
 1704204813            } else if (d is RedirectingTypeDecl) {
 759084814              var dd = (RedirectingTypeDecl)d;
 759084815              var caller = CodeContextWrapper.Unwrap(resolutionContext.CodeContext) as ICallable;
 1515924816              if (caller != null && !(d is SubsetTypeDecl && caller is SpecialFunction)) {
 1513684817                if (caller != d) {
 756844818                } else if (d is TypeSynonymDecl && !(d is SubsetTypeDecl)) {
 4819                  // detect self-loops here, since they don't show up in the graph's SCC methods
 04820                  reporter.Error(MessageSource.Resolver, d.tok, "type-synonym cycle: {0} -> {0}", d.Name);
 04821                } else {
 4822                  // detect self-loops here, since they don't show up in the graph's SCC methods
 04823                  reporter.Error(MessageSource.Resolver, d.tok, "recursive constraint dependency involving a {0}: {1} ->
 04824                }
 756844825              }
 759084826              t.ResolvedClass = d;
 1107284827            } else if (d is DatatypeDecl) {
 162164828              t.ResolvedClass = d;
 186044829            } else {
 4830              // d is a type parameter, coinductive datatype, or class, and it may have type parameters
 23884831              t.ResolvedClass = d;
 23884832            }
 1663914833            if (option.Opt == ResolveTypeOptionEnum.DontInfer) {
 4834              // don't add anything
 945124835            } else if (d.TypeArgs.Count != t.TypeArgs.Count && t.TypeArgs.Count == 0) {
 04836              FillInTypeArguments(t.tok, d.TypeArgs.Count, t.TypeArgs, defaultTypeArguments, option);
 04837            }
 4838            // defaults and auto have been applied; check if we now have the right number of arguments
 945124839            if (d.TypeArgs.Count != t.TypeArgs.Count) {
 04840              reporter.Error(MessageSource.Resolver, t.tok, "Wrong number of type arguments ({0} instead of {1}) passed 
 04841            }
 4842
 945124843          }
 945124844        }
 945124845        if (t.ResolvedClass == null) {
 4846          // There was some error. Still, we will set .ResolvedClass to some value to prevent some crashes in the downst
 4847          // 0-tuple is convenient, because it is always in scope.
 04848          t.ResolvedClass = builtIns.TupleType(t.tok, 0, false);
 4849          // clear out the TypeArgs since 0-tuple doesn't take TypeArg
 04850          t.TypeArgs = new List<Type>();
 04851        }
 4852
 1061324853      } else if (type is TypeProxy) {
 56984854        TypeProxy t = (TypeProxy)type;
 56984855        if (t.T != null) {
 04856          ResolveType(tok, t.T, resolutionContext, option, defaultTypeArguments);
 04857        }
 61464858      } else if (type is SelfType) {
 4859        // do nothing.
 2244860      } else {
 04861        Contract.Assert(false); throw new cce.UnreachableException();  // unexpected type
 4862      }
 2011644863      return null;
 2020214864    }
 4865
 4866    /// <summary>
 4867    /// Adds to "typeArgs" a list of "n" type arguments, possibly extending "defaultTypeArguments".
 4868    /// </summary>
 4484869    static void FillInTypeArguments(IToken tok, int n, List<Type> typeArgs, List<TypeParameter> defaultTypeArguments, Re
 4870      Contract.Requires(tok != null);
 4871      Contract.Requires(0 <= n);
 4872      Contract.Requires(typeArgs != null && typeArgs.Count == 0);
 6724873      if (option.Opt == ResolveTypeOptionEnum.InferTypeProxies) {
 4874        // add type arguments that will be inferred
 11204875        for (int i = 0; i < n; i++) {
 2244876          typeArgs.Add(new InferredTypeProxy());
 2244877        }
 4484878      } else if (option.Opt == ResolveTypeOptionEnum.AllowPrefix && defaultTypeArguments.Count < n) {
 4879        // there aren't enough default arguments, so don't do anything
 2244880      } else {
 4881        // we'll add arguments
 4484882        if (option.Opt == ResolveTypeOptionEnum.AllowPrefixExtend) {
 4883          // extend defaultTypeArguments, if needed
 11204884          for (int i = defaultTypeArguments.Count; i < n; i++) {
 2244885            var tp = new TypeParameter(tok.ToRange(), new Name(tok.ToRange(), "_T" + i), i, option.Parent);
 2244886            if (option.Parent is IteratorDecl) {
 04887              tp.Characteristics.AutoInit = Type.AutoInitInfo.CompilableValue;
 04888            }
 2244889            defaultTypeArguments.Add(tp);
 2244890          }
 2244891        }
 2244892        Contract.Assert(n <= defaultTypeArguments.Count);
 4893        // automatically supply a prefix of the arguments from defaultTypeArguments
 11204894        for (int i = 0; i < n; i++) {
 2244895          typeArgs.Add(new UserDefinedType(defaultTypeArguments[i]));
 2244896        }
 2244897      }
 4484898    }
 4899
 6524900    public static bool TypeConstraintsIncludeProxy(Type t, TypeProxy proxy) {
 6524901      return TypeConstraintsIncludeProxy_Aux(t, proxy, new HashSet<TypeProxy>());
 6524902    }
 9144903    static bool TypeConstraintsIncludeProxy_Aux(Type t, TypeProxy proxy, ISet<TypeProxy> visited) {
 4904      Contract.Requires(t != null);
 4905      Contract.Requires(!(t is TypeProxy) || ((TypeProxy)t).T == null);  // t is expected to have been normalized first
 4906      Contract.Requires(proxy != null && proxy.T == null);
 4907      Contract.Requires(visited != null);
 9144908      var tproxy = t as TypeProxy;
 9144909      if (tproxy != null) {
 04910        if (object.ReferenceEquals(tproxy, proxy)) {
 04911          return true;
 04912        } else if (visited.Contains(tproxy)) {
 04913          return false;
 4914        }
 04915        visited.Add(tproxy);
 04916        foreach (var su in tproxy.Subtypes) {
 04917          if (TypeConstraintsIncludeProxy_Aux(su, proxy, visited)) {
 04918            return true;
 4919          }
 04920        }
 04921        foreach (var su in tproxy.Supertypes) {
 04922          if (TypeConstraintsIncludeProxy_Aux(su, proxy, visited)) {
 04923            return true;
 4924          }
 04925        }
 9144926      } else {
 4927        // check type arguments of t
 35284928        foreach (var ta in t.TypeArgs) {
 2624929          var a = ta.Normalize();
 2624930          if (TypeConstraintsIncludeProxy_Aux(a, proxy, visited)) {
 04931            return true;
 4932          }
 2624933        }
 9144934      }
 9144935      return false;
 9144936    }
 4937
 70004938    public Type ResolveTypeRhs(TypeRhs rr, Statement stmt, ResolutionContext resolutionContext) {
 4939      Contract.Requires(rr != null);
 4940      Contract.Requires(stmt != null);
 4941      Contract.Requires(resolutionContext != null);
 4942      Contract.Ensures(Contract.Result<Type>() != null);
 4943
 105004944      if (rr.Type == null) {
 70004945        if (rr.ArrayDimensions != null) {
 4946          // ---------- new T[EE]    OR    new T[EE] (elementInit)
 35004947          Contract.Assert(rr.Bindings == null && rr.Path == null && rr.InitCall == null);
 35004948          ResolveType(stmt.Tok, rr.EType, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 35004949          int i = 0;
 210004950          foreach (Expression dim in rr.ArrayDimensions) {
 35004951            Contract.Assert(dim != null);
 35004952            ResolveExpression(dim, resolutionContext);
 35004953            ConstrainToIntegerType(dim, false, string.Format("new must use an integer-based expression for the array siz
 35004954            i++;
 35004955          }
 35004956          rr.Type = ResolvedArrayType(stmt.Tok, rr.ArrayDimensions.Count, rr.EType, resolutionContext, false);
 35004957          if (rr.ElementInit != null) {
 04958            ResolveExpression(rr.ElementInit, resolutionContext);
 4959            // Check
 4960            //     int^N -> rr.EType  :>  rr.ElementInit.Type
 04961            builtIns.CreateArrowTypeDecl(rr.ArrayDimensions.Count);  // TODO: should this be done already in the parser?
 04962            var args = new List<Type>();
 04963            for (int ii = 0; ii < rr.ArrayDimensions.Count; ii++) {
 04964              args.Add(builtIns.Nat());
 04965            }
 04966            var arrowType = new ArrowType(rr.ElementInit.tok, builtIns.ArrowTypeDecls[rr.ArrayDimensions.Count], args, r
 04967            var lambdaType = rr.ElementInit.Type.AsArrowType;
 04968            if (lambdaType != null && lambdaType.TypeArgs[0] is InferredTypeProxy) {
 04969              (lambdaType.TypeArgs[0] as InferredTypeProxy).KeepConstraints = true;
 04970            }
 4971            string underscores;
 04972            if (rr.ArrayDimensions.Count == 1) {
 04973              underscores = "_";
 04974            } else {
 04975              underscores = "(" + Util.Comma(rr.ArrayDimensions.Count, x => "_") + ")";
 04976            }
 04977            var hintString = string.Format(" (perhaps write '{0} =>' in front of the expression you gave in order to mak
 04978            ConstrainSubtypeRelation(arrowType, rr.ElementInit.Type, rr.ElementInit, "array-allocation initialization ex
 04979              arrowType, rr.ElementInit.Type, new LazyString_OnTypeEquals(rr.EType, rr.ElementInit.Type, hintString));
 66304980          } else if (rr.InitDisplay != null) {
 468904981            foreach (var v in rr.InitDisplay) {
 125004982              ResolveExpression(v, resolutionContext);
 125004983              AddAssignableConstraint(v.tok, rr.EType, v.Type, "initial value must be assignable to array's elements (ex
 125004984            }
 31304985          }
 35004986        } else {
 04987          bool callsConstructor = false;
 04988          if (rr.Bindings == null) {
 04989            ResolveType(stmt.Tok, rr.EType, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 04990            var cl = (rr.EType as UserDefinedType)?.ResolvedClass as NonNullTypeDecl;
 04991            if (cl != null && !(rr.EType.IsTraitType && !rr.EType.NormalizeExpand().IsObjectQ)) {
 4992              // life is good
 04993            } else {
 04994              reporter.Error(MessageSource.Resolver, rr.tok, "new can be applied only to class types (got {0})", rr.ETyp
 04995            }
 04996          } else {
 04997            string initCallName = null;
 04998            IToken initCallTok = null;
 4999            // Resolve rr.Path and do one of three things:
 5000            // * If rr.Path denotes a type, then set EType,initCallName to rr.Path,"_ctor", which sets up a call to the 
 5001            // * If the all-but-last components of rr.Path denote a type, then do EType,initCallName := allButLast(EType
 5002            // * Otherwise, report an error
 05003            var ret = ResolveTypeLenient(rr.Tok, rr.Path, resolutionContext, new ResolveTypeOption(ResolveTypeOptionEnum
 05004            if (ret != null) {
 5005              // The all-but-last components of rr.Path denote a type (namely, ret.ReplacementType).
 05006              rr.EType = ret.ReplacementType;
 05007              initCallName = ret.LastComponent.SuffixName;
 05008              initCallTok = ret.LastComponent.tok;
 05009            } else {
 5010              // Either rr.Path resolved correctly as a type or there was no way to drop a last component to make it int
 5011              // like a type.  In either case, set EType,initCallName to Path,"_ctor" and continue.
 05012              rr.EType = rr.Path;
 05013              initCallName = "_ctor";
 05014              initCallTok = rr.Tok;
 05015            }
 05016            var cl = (rr.EType as UserDefinedType)?.ResolvedClass as NonNullTypeDecl;
 05017            if (cl == null || rr.EType.IsTraitType) {
 05018              reporter.Error(MessageSource.Resolver, rr.tok, "new can be applied only to class types (got {0})", rr.ETyp
 05019            } else {
 5020              // ---------- new C.Init(EE)
 05021              Contract.Assert(initCallName != null);
 05022              var prevErrorCount = reporter.Count(ErrorLevel.Error);
 5023
 5024              // We want to create a MemberSelectExpr for the initializing method.  To do that, we create a throw-away r
 5025              // type, create a dot-suffix expression around this receiver, and then resolve it in the usual way for dot
 05026              var lhs = new ImplicitThisExpr_ConstructorCall(initCallTok) { Type = rr.EType };
 05027              var callLhs = new ExprDotName(((UserDefinedType)rr.EType).tok, lhs, initCallName, ret == null ? null : ret
 05028              ResolveDotSuffix(callLhs, true, rr.Bindings.ArgumentBindings, resolutionContext, true);
 05029              if (prevErrorCount == reporter.Count(ErrorLevel.Error)) {
 05030                Contract.Assert(callLhs.ResolvedExpression is MemberSelectExpr);  // since ResolveApplySuffix succeeded 
 05031                var methodSel = (MemberSelectExpr)callLhs.ResolvedExpression;
 05032                if (methodSel.Member is Method) {
 05033                  rr.InitCall = new CallStmt(stmt.RangeToken, new List<Expression>(), methodSel, rr.Bindings.ArgumentBin
 05034                  ResolveCallStmt(rr.InitCall, resolutionContext, rr.EType);
 05035                  if (rr.InitCall.Method is Constructor) {
 05036                    callsConstructor = true;
 05037                  }
 05038                } else {
 05039                  reporter.Error(MessageSource.Resolver, initCallTok, "object initialization must denote an initializing
 05040                }
 05041              }
 05042            }
 05043          }
 05044          if (rr.EType.IsRefType) {
 05045            var udt = rr.EType.NormalizeExpand() as UserDefinedType;
 05046            if (udt != null) {
 05047              var cl = (ClassDecl)udt.ResolvedClass;  // cast is guaranteed by the call to rr.EType.IsRefType above, tog
 05048              if (!callsConstructor && !cl.IsObjectTrait && !udt.IsArrayType && (cl.HasConstructor || cl.EnclosingModule
 05049                reporter.Error(MessageSource.Resolver, stmt, "when allocating an object of {1}type '{0}', one of its con
 05050                  cl.HasConstructor ? "" : "imported ");
 05051              }
 05052            }
 05053          }
 05054          rr.Type = rr.EType;
 05055        }
 35005056      }
 70005057      return rr.Type;
 70005058    }
 5059
 5060    /// <summary>
 5061    /// Resolve "memberName" in what currently is known as "receiverType". If "receiverType" is an unresolved
 5062    /// proxy type, try to solve enough type constraints and use heuristics to figure out which type contains
 5063    /// "memberName" and return that enclosing type as "tentativeReceiverType". However, try not to make
 5064    /// type-inference decisions about "receiverType"; instead, lay down the further constraints that need to
 5065    /// be satisfied in order for "tentativeReceiverType" to be where "memberName" is found.
 5066    /// Consequently, if "memberName" is found and returned as a "MemberDecl", it may still be the case that
 5067    /// "receiverType" is an unresolved proxy type and that, after solving more type constraints, "receiverType"
 5068    /// eventually gets set to a type more specific than "tentativeReceiverType".
 5069    /// </summary>
 78245070    public MemberDecl ResolveMember(IToken tok, Type receiverType, string memberName, out NonProxyType tentativeReceiver
 5071      Contract.Requires(tok != null);
 5072      Contract.Requires(receiverType != null);
 5073      Contract.Requires(memberName != null);
 5074      Contract.Ensures(Contract.Result<MemberDecl>() == null || Contract.ValueAtReturn(out tentativeReceiverType) != nul
 5075
 78245076      receiverType = PartiallyResolveTypeForMemberSelection(tok, receiverType, memberName);
 5077
 78245078      if (receiverType is TypeProxy) {
 05079        reporter.Error(MessageSource.Resolver, tok, "type of the receiver is not fully determined at this program point"
 05080        tentativeReceiverType = null;
 05081        return null;
 5082      }
 78245083      Contract.Assert(receiverType is NonProxyType);  // there are only two kinds of types: proxies and non-proxies
 5084
 1858115085      foreach (var valuet in valuetypeDecls) {
 543335086        if (valuet.IsThisType(receiverType)) {
 3305087          if (valuet.Members.TryGetValue(memberName, out var member)) {
 1655088            SelfType resultType = null;
 1655089            if (member is SpecialFunction) {
 05090              resultType = ((SpecialFunction)member).ResultType as SelfType;
 3305091            } else if (member is SpecialField) {
 1655092              resultType = ((SpecialField)member).Type as SelfType;
 1655093            }
 1655094            if (resultType != null) {
 05095              SelfTypeSubstitution = new Dictionary<TypeParameter, Type>();
 05096              SelfTypeSubstitution.Add(resultType.TypeArg, receiverType);
 05097              resultType.ResolvedType = receiverType;
 05098            }
 1655099            tentativeReceiverType = (NonProxyType)receiverType;
 1655100            return member;
 5101          }
 05102          break;
 5103        }
 540035104      }
 5105
 76595106      var ctype = receiverType.NormalizeExpand() as UserDefinedType;
 76595107      var cd = ctype?.AsTopLevelTypeWithMembersBypassInternalSynonym;
 153185108      if (cd != null) {
 76595109        Contract.Assert(ctype.TypeArgs.Count == cd.TypeArgs.Count);  // follows from the fact that ctype was resolved
 76595110        if (!classMembers[cd].TryGetValue(memberName, out var member)) {
 05111          if (memberName == "_ctor") {
 05112            reporter.Error(MessageSource.Resolver, tok, "{0} {1} does not have an anonymous constructor", cd.WhatKind, c
 05113          } else {
 05114            reporter.Error(MessageSource.Resolver, tok, "member '{0}' does not exist in {2} '{1}'", memberName, cd.Name,
 05115          }
 76595116        } else if (!VisibleInScope(member)) {
 05117          reporter.Error(MessageSource.Resolver, tok, "member '{0}' has not been imported in this scope and cannot be ac
 76595118        } else {
 76595119          tentativeReceiverType = ctype;
 76595120          return member;
 5121        }
 05122        tentativeReceiverType = null;
 05123        return null;
 5124      }
 5125
 05126      reporter.Error(MessageSource.Resolver, tok, "type {0} does not have a member {1}", receiverType, memberName);
 05127      tentativeReceiverType = null;
 05128      return null;
 78245129    }
 5130
 5131    /// <summary>
 5132    /// Roughly speaking, tries to figure out the head of the type of "t", making as few inference decisions as possible
 5133    /// More precisely, returns a type that contains all the members of "t"; or if "memberName" is non-null, a type
 5134    /// that at least contains the member "memberName" of "t".  Typically, this type is the head type of "t",
 5135    /// but it may also be a type in a super- or subtype relation to "t".
 5136    /// In some cases, it is necessary to make some inference decisions in order to figure out the type to return.
 5137    /// </summary>
 453995138    public Type PartiallyResolveTypeForMemberSelection(IToken tok, Type t, string memberName = null, int strength = 0) {
 5139      Contract.Requires(tok != null);
 5140      Contract.Requires(t != null);
 5141      Contract.Ensures(Contract.Result<Type>() != null);
 5142      Contract.Ensures(!(Contract.Result<Type>() is TypeProxy) || ((TypeProxy)Contract.Result<Type>()).T == null);
 453995143      t = t.NormalizeExpand();
 714175144      if (!(t is TypeProxy)) {
 260185145        return t;  // we're good
 5146      }
 5147
 5148      // simplify constraints
 193815149      PrintTypeConstraintState(10);
 263235150      if (strength > 0) {
 69425151        var proxySpecializations = new HashSet<TypeProxy>();
 69425152        GetRelatedTypeProxies(t, proxySpecializations);
 69425153        var anyNewConstraintsAssignable = ConvertAssignableToSubtypeConstraints(proxySpecializations);
 69425154        var anyNewConstraintsEquatable = TightenUpEquatable(proxySpecializations);
 104135155        if ((strength > 1 && !anyNewConstraintsAssignable && !anyNewConstraintsEquatable) || strength == 10) {
 69425156          if (t is TypeProxy) {
 5157            // One more try
 34715158            var r = GetBaseTypeFromProxy((TypeProxy)t, new Dictionary<TypeProxy, Type>());
 34715159            if (r != null) {
 05160              if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05161                Options.OutputWriter.WriteLine("  ----> found improvement through GetBaseTypeFromProxy: {0}", r);
 05162              }
 05163              return r;
 5164            }
 34715165          }
 5166
 34715167          if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05168            Options.OutputWriter.WriteLine("  ----> found no improvement, giving up");
 05169          }
 34715170          return t;
 5171        }
 34715172      }
 159105173      PartiallySolveTypeConstraints(false);
 159105174      PrintTypeConstraintState(11);
 159105175      t = t.NormalizeExpandKeepConstraints();
 159105176      var proxy = t as TypeProxy;
 161255177      if (proxy == null) {
 2155178        return t;  // simplification did the trick
 5179      }
 156955180      if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05181        Options.OutputWriter.WriteLine("DEBUG: Member selection{3}:  {1} :> {0} :> {2}", t,
 05182          Util.Comma(proxy.SupertypesKeepConstraints, su => su.ToString()),
 05183          Util.Comma(proxy.SubtypesKeepConstraints, su => su.ToString()),
 05184          memberName == null ? "" : " (" + memberName + ")");
 05185      }
 5186
 5187      // Look for a join of head symbols among the proxy's subtypes
 156955188      Type joinType = null;
 158405189      if (JoinOfAllSubtypes(proxy, ref joinType, new HashSet<TypeProxy>()) && joinType != null) {
 1455190        DetermineRootLeaf(joinType, out _, out _, out var headIsRoot, out _);
 1455191        if (joinType.IsDatatype) {
 05192          if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05193            Options.OutputWriter.WriteLine("  ----> join is a datatype: {0}", joinType);
 05194          }
 05195          ConstrainSubtypeRelation(t, joinType, tok, "Member selection requires a supertype of {0} (got something more l
 05196          return joinType;
 2105197        } else if (headIsRoot) {
 5198          // we're good to go -- by picking "join" (whose type parameters have been replaced by fresh proxies), we're no
 655199          if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05200            Options.OutputWriter.WriteLine("  ----> improved to {0} through join", joinType);
 05201          }
 655202          AssignProxyAndHandleItsConstraints(proxy, joinType, true);
 655203          return proxy.NormalizeExpand();  // we return proxy.T instead of join, in case the assignment gets hijacked
 805204        } else if (memberName == "_#apply" || memberName == "requires" || memberName == "reads") {
 05205          var generalArrowType = joinType.AsArrowType;  // go all the way to the base type, to get to the general arrow 
 05206          if (generalArrowType != null) {
 5207            // pick the supertype "generalArrowType" of "join"
 05208            if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05209              Options.OutputWriter.WriteLine("  ----> improved to {0} through join and function application", generalArr
 05210            }
 05211            ConstrainSubtypeRelation(generalArrowType, t, tok, "Function application requires a subtype of {0} (got some
 05212            return generalArrowType;
 5213          }
 1605214        } else if (memberName != null) {
 5215          // If "join" has a member called "memberName" and no supertype of "join" does, then we'll pick this join
 1605216          if (joinType.IsRefType) {
 805217            var joinExpanded = joinType.NormalizeExpand();  // go all the way to the base type, to get to the class
 1605218            if (!joinExpanded.IsObjectQ) {
 805219              var cl = ((UserDefinedType)joinExpanded).ResolvedClass as ClassDecl;
 1605220              if (cl != null) {
 5221                // TODO: the following could be improved by also supplying an upper bound of the search (computed as a j
 805222                var plausibleMembers = new HashSet<MemberDecl>();
 805223                FindAllMembers(cl, memberName, plausibleMembers);
 1605224                if (plausibleMembers.Count == 1) {
 805225                  var mbr = plausibleMembers.First();
 1605226                  if (mbr.EnclosingClass == cl) {
 805227                    if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05228                      Options.OutputWriter.WriteLine("  ----> improved to {0} through member-selection join", joinType);
 05229                    }
 805230                    var joinRoot = joinType.NormalizeExpand();  // blow passed any constraints
 805231                    ConstrainSubtypeRelation(joinRoot, t, tok, "Member selection requires a subtype of {0} (got somethin
 805232                    return joinType;
 05233                  } else {
 5234                    // pick the supertype "mbr.EnclosingClass" of "cl"
 05235                    Contract.Assert(mbr.EnclosingClass is TraitDecl);  // a proper supertype of a ClassDecl must be a Tr
 05236                    var typeMapping = cl.ParentFormalTypeParametersToActuals;
 05237                    TopLevelDecl td = mbr.EnclosingClass;
 05238                    foreach (var tt in cl.TraitAncestors()) {
 5239                      // If there is a match, the list of Type actuals is unique
 5240                      // (a class cannot inherit both Trait<T1> and Trait<T2> with T1 != T2).
 05241                      if (tt == (TraitDecl)mbr.EnclosingClass) {
 05242                        td = tt;
 05243                      }
 05244                    }
 05245                    List<Type> proxyTypeArgs = td.TypeArgs.ConvertAll(t0 => typeMapping.ContainsKey(t0) ? typeMapping[t0
 05246                    var joinMapping = TypeParameter.SubstitutionMap(cl.TypeArgs, joinType.TypeArgs);
 05247                    proxyTypeArgs = proxyTypeArgs.ConvertAll(t0 => t0.Subst(joinMapping));
 05248                    proxyTypeArgs = proxyTypeArgs.ConvertAll(t0 => t0.AsTypeParameter == null ? t0 : (Type)new InferredT
 05249                    var pickItFromHere = new UserDefinedType(tok, mbr.EnclosingClass.Name, mbr.EnclosingClass, proxyType
 05250                    if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05251                      Options.OutputWriter.WriteLine("  ----> improved to {0} through join and member lookup", pickItFro
 05252                    }
 05253                    ConstrainSubtypeRelation(pickItFromHere, t, tok, "Member selection requires a subtype of {0} (got so
 05254                    return pickItFromHere;
 5255                  }
 5256                }
 05257              }
 05258            }
 05259          }
 05260        }
 05261        if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05262          Options.OutputWriter.WriteLine("  ----> found no improvement, because join does not determine type enough");
 05263        }
 05264      }
 5265
 5266      // Compute the meet of the proxy's supertypes
 155505267      Type meet = null;
 239885268      if (MeetOfAllSupertypes(proxy, ref meet, new HashSet<TypeProxy>(), false) && meet != null) {
 5269        // If the meet does have the member, then this looks promising. It could be that the
 5270        // type would get further constrained later to pick some subtype (in particular, a
 5271        // subclass that overrides the member) of this meet. But this is the best we can do
 5272        // now.
 84385273        if (meet is TypeProxy) {
 05274          if (proxy == meet.Normalize()) {
 5275            // can this really ever happen?
 05276            if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05277              Options.OutputWriter.WriteLine("  ----> found no improvement (other than the proxy itself)");
 05278            }
 05279            return t;
 05280          } else {
 05281            if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05282              Options.OutputWriter.WriteLine("  ----> (merging, then trying to improve further) assigning proxy {0}.T :=
 05283            }
 05284            Contract.Assert(proxy != meet);
 05285            proxy.T = meet;
 05286            Contract.Assert(t.NormalizeExpand() == meet);
 05287            return PartiallyResolveTypeForMemberSelection(tok, t, memberName, strength + 1);
 5288          }
 5289        }
 84385290        if (!(meet is ArtificialType)) {
 05291          if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05292            Options.OutputWriter.WriteLine("  ----> improved to {0} through meet", meet);
 05293          }
 05294          if (memberName != null) {
 05295            AssignProxyAndHandleItsConstraints(proxy, meet, true);
 05296            return proxy.NormalizeExpand(); // we return proxy.T instead of meet, in case the assignment gets hijacked
 05297          } else {
 05298            return meet;
 5299          }
 5300        }
 84385301      }
 5302
 5303      // as a last resort, act on any artificial type nearby the proxy
 155505304      var artificialSuper = proxy.InClusterOfArtificial(AllXConstraints);
 241585305      if (artificialSuper != null) {
 86085306        if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05307          Options.OutputWriter.WriteLine("  ----> use artificial supertype: {0}", artificialSuper);
 05308        }
 86085309        return artificialSuper;
 5310      }
 5311
 5312      // we weren't able to do it
 69425313      if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05314        Options.OutputWriter.WriteLine("  ----> found no improvement using simple things, trying harder once more");
 05315      }
 69425316      return PartiallyResolveTypeForMemberSelection(tok, t, memberName, strength + 1);
 453995317    }
 5318
 34715319    private Type/*?*/ GetBaseTypeFromProxy(TypeProxy proxy, Dictionary<TypeProxy, Type/*?*/> determinedProxies) {
 5320      Contract.Requires(proxy != null);
 5321      Contract.Requires(determinedProxies != null);
 34715322      if (determinedProxies.TryGetValue(proxy, out var t)) {
 5323        // "t" may be null (meaning search for "proxy" is underway or was unsuccessful) or non-null (search for
 5324        // "proxy" has completed successfully), but we return it in either case
 05325        return t;
 5326      }
 34715327      determinedProxies.Add(proxy, null);  // record that search for "proxy" is underway
 5328      // First, go through subtype constraints, treating each as if it were an equality
 16075505329      foreach (var c in AllTypeConstraints) {
 5323795330        t = GetBaseTypeFromProxy_Eq(proxy, c.Super, c.Sub, determinedProxies);
 5323795331        if (t != null) {
 05332          determinedProxies[proxy] = t;
 05333          return t;
 5334        }
 5323795335      }
 5336      // Next, check XConstraints that can be seen as equality constraints
 5097755337      foreach (var xc in AllXConstraints) {
 1664545338        switch (xc.ConstraintName) {
 5339          case "Assignable":
 5340          case "Equatable":
 5341          case "EquatableArg":
 1281395342            t = GetBaseTypeFromProxy_Eq(proxy, xc.Types[0], xc.Types[1], determinedProxies);
 1281395343            if (t != null) {
 05344              determinedProxies[proxy] = t;
 05345              return t;
 5346            }
 1281395347            break;
 5348          case "InSet":
 5349            // etc. TODO
 05350            break;
 5351          default:
 383155352            break;
 5353        }
 1664545354      }
 34715355      return null;
 34715356    }
 5357    /// <summary>
 5358    /// Tries to find a non-proxy type corresponding to "proxy", under the assumption that "t" equals "u" and
 5359    /// "determinedProxies" assumptions.  In the process, may add to "determinedProxies".
 5360    /// </summary>
 6605185361    private Type/*?*/ GetBaseTypeFromProxy_Eq(TypeProxy proxy, Type t, Type u, Dictionary<TypeProxy, Type/*?*/> determin
 5362      Contract.Requires(proxy != null);
 5363      Contract.Requires(determinedProxies != null);
 5364      Contract.Requires(t != null);
 5365      Contract.Requires(u != null);
 6605185366      t = t.NormalizeExpand();
 6605185367      u = u.NormalizeExpand();
 6605185368      return GetBaseTypeFromProxy_EqAux(proxy, t, u, determinedProxies) ?? GetBaseTypeFromProxy_EqAux(proxy, u, t, deter
 6605185369    }
 13210365370    private Type/*?*/ GetBaseTypeFromProxy_EqAux(TypeProxy proxy, Type t, Type u, Dictionary<TypeProxy, Type/*?*/> deter
 5371      Contract.Requires(proxy != null);
 5372      Contract.Requires(determinedProxies != null);
 5373      Contract.Requires(t != null && (!(t is TypeProxy) || ((TypeProxy)t).T == null));
 5374      Contract.Requires(u != null && (!(u is TypeProxy) || ((TypeProxy)u).T == null));
 13210365375      if (t == proxy) {
 05376        if (u is TypeProxy) {
 05377          return GetBaseTypeFromProxy((TypeProxy)u, determinedProxies);
 05378        } else {
 05379          return u;
 5380        }
 13210365381      } else if (t.ContainsProxy(proxy)) {
 05382        if (u is TypeProxy) {
 05383          u = GetBaseTypeFromProxy((TypeProxy)u, determinedProxies);
 05384          if (u == null) {
 05385            return null;
 5386          }
 05387        }
 05388        if (Type.SameHead(t, u)) {
 05389          Contract.Assert(t.TypeArgs.Count == u.TypeArgs.Count);
 05390          for (int i = 0; i < t.TypeArgs.Count; i++) {
 05391            var r = GetBaseTypeFromProxy_Eq(proxy, t.TypeArgs[i], u.TypeArgs[i], determinedProxies);
 05392            if (r != null) {
 05393              return r;
 5394            }
 05395          }
 05396        }
 05397      }
 13210365398      return null;
 13210365399    }
 5400
 69425401    private void GetRelatedTypeProxies(Type t, ISet<TypeProxy> proxies) {
 5402      Contract.Requires(t != null);
 5403      Contract.Requires(proxies != null);
 69425404      var proxy = t.Normalize() as TypeProxy;
 69425405      if (proxy == null || proxies.Contains(proxy)) {
 05406        return;
 5407      }
 69425408      if (Options.Get(CommonOptionBag.TypeInferenceDebug)) {
 05409        Options.OutputWriter.WriteLine("DEBUG: GetRelatedTypeProxies: finding {0} interesting", proxy);
 05410      }
 69425411      proxies.Add(proxy);
 5412      // close over interesting constraints
 32151005413      foreach (var c in AllTypeConstraints) {
 10647585414        var super = c.Super.Normalize();
 10867185415        if (super.TypeArgs.Exists(ta => ta.Normalize() == proxy)) {
 05416          GetRelatedTypeProxies(c.Sub, proxies);
 05417        }
 10647585418      }
 10195505419      foreach (var xc in AllXConstraints) {
 3329085420        var xc0 = xc.Types[0].Normalize();
 3330885421        if (xc.ConstraintName == "Assignable" && (xc0 == proxy || xc0.TypeArgs.Exists(ta => ta.Normalize() == proxy))) {
 05422          GetRelatedTypeProxies(xc.Types[1], proxies);
 3329085423        } else if (xc.ConstraintName == "Innable" && xc.Types[1].Normalize() == proxy) {
 05424          GetRelatedTypeProxies(xc.Types[0], proxies);
 3329085425        } else if ((xc.ConstraintName == "ModifiesFrame" || xc.ConstraintName == "ReadsFrame") && xc.Types[1].Normalize(
 05426          GetRelatedTypeProxies(xc.Types[0], proxies);
 05427        }
 3329085428      }
 69425429    }
 5430
 5431    /// <summary>
 5432    /// Attempts to compute the join of "join", "t", and all of "t"'s known subtype( constraint)s.  The join
 5433    /// ignores type parameters.  It is assumed that "join" on entry already includes the join of all proxies
 5434    /// in "visited". The empty join is represented by "null".
 5435    /// The return is "true" if the join exists.
 5436    /// </summary>
 164305437    bool JoinOfAllSubtypes(Type t, ref Type joinType, ISet<TypeProxy> visited) {
 5438      Contract.Requires(t != null);
 5439      Contract.Requires(visited != null);
 5440
 164305441      t = t.NormalizeExpandKeepConstraints();
 5442
 164305443      var proxy = t as TypeProxy;
 325505444      if (proxy != null) {
 161205445        if (visited.Contains(proxy)) {
 05446          return true;
 5447        }
 161205448        visited.Add(proxy);
 5449
 501755450        foreach (var c in proxy.SubtypeConstraints) {
 6055451          var s = c.Sub.NormalizeExpandKeepConstraints();
 6055452          if (!JoinOfAllSubtypes(s, ref joinType, visited)) {
 05453            return false;
 5454          }
 6055455        }
 320055456        if (joinType == null) {
 5457          // also consider "Assignable" constraints
 30213035458          foreach (var c in AllXConstraints) {
 9913465459            if (c.ConstraintName == "Assignable" && c.Types[0].Normalize() == proxy) {
 1305460              var s = c.Types[1].NormalizeExpandKeepConstraints();
 1305461              if (!JoinOfAllSubtypes(s, ref joinType, visited)) {
 05462                return false;
 5463              }
 1305464            }
 9912165465          }
 158855466        }
 161205467        return true;
 5468      }
 5469
 4555470      if (joinType == null) {
 5471        // stick with what we've got
 1455472        joinType = t;
 1455473        return true;
 2805474      } else if (Type.IsHeadSupertypeOf(joinType, t)) {
 5475        // stick with what we've got
 1155476        return true;
 1005477      } else if (Type.IsHeadSupertypeOf(t, joinType)) {
 505478        joinType = Type.HeadWithProxyArgs(t);
 505479        return true;
 05480      } else {
 05481        joinType = Type.Join(joinType, Type.HeadWithProxyArgs(t), builtIns);  // the only way this can succeed is if we 
 05482        Contract.Assert(joinType == null ||
 05483                        joinType.IsObjectQ || joinType.IsObject ||
 05484                        (joinType is UserDefinedType udt && (udt.ResolvedClass is TraitDecl || (udt.ResolvedClass is Non
 05485        return joinType != null;
 5486      }
 164305487    }
 5488
 5489    /// <summary>
 5490    /// Attempts to compute the meet of "meet", all of "t"'s known supertype( constraint)s, and, if "includeT"
 5491    /// and "t" has no supertype( constraint)s, "t".
 5492    /// The meet ignores type parameters. (Really?? --KRML)
 5493    /// It is assumed that "meet" on entry already includes the meet of all proxies
 5494    /// in "visited". The empty meet is represented by "null".
 5495    /// The return is "true" if the meet exists.
 5496    /// </summary>
 240885497    bool MeetOfAllSupertypes(Type t, ref Type meet, ISet<TypeProxy> visited, bool includeT) {
 5498      Contract.Requires(t != null);
 5499      Contract.Requires(visited != null);
 5500
 240885501      t = t.NormalizeExpandKeepConstraints();
 240885502      var proxy = t as TypeProxy;
 397385503      if (proxy != null) {
 156605504        if (visited.Contains(proxy)) {
 105505          return true;
 5506        }
 156405507        visited.Add(proxy);
 5508
 156405509        var delegatedToOthers = false;
 723095510        foreach (var c in proxy.SupertypeConstraints) {
 84635511          var s = c.Super.NormalizeExpandKeepConstraints();
 84635512          delegatedToOthers = true;
 84635513          if (!MeetOfAllSupertypes(s, ref meet, visited, true)) {
 05514            return false;
 5515          }
 84635516        }
 228275517        if (!delegatedToOthers) {
 5518          // also consider "Assignable" constraints
 11080505519          foreach (var c in AllXConstraints) {
 3621635520            if (c.ConstraintName == "Assignable" && c.Types[1].Normalize() == proxy) {
 05521              var s = c.Types[0].NormalizeExpandKeepConstraints();
 05522              delegatedToOthers = true;
 05523              if (!MeetOfAllSupertypes(s, ref meet, visited, true)) {
 05524                return false;
 5525              }
 05526            }
 3621635527          }
 71875528        }
 240935529        if (delegatedToOthers) {
 84535530          return true;
 143595531        } else if (!includeT) {
 71725532          return true;
 305533        } else if (meet == null || meet.Normalize() == proxy) {
 155534          meet = proxy;
 155535          return true;
 05536        } else {
 05537          return false;
 5538        }
 5539      }
 5540
 168765541      if (meet == null) {
 84385542        meet = Type.HeadWithProxyArgs(t);
 84385543        return true;
 05544      } else if (Type.IsHeadSupertypeOf(t, meet)) {
 5545        // stick with what we've got
 05546        return true;
 05547      } else if (Type.IsHeadSupertypeOf(meet, t)) {
 05548        meet = Type.HeadWithProxyArgs(t);
 05549        return true;
 05550      } else {
 05551        meet = Type.Meet(meet, Type.HeadWithProxyArgs(t), builtIns);
 05552        return meet != null;
 5553      }
 240885554    }
 5555
 5556    /// <summary>
 5557    /// Check that the type uses formal type parameters in a way that is agreeable with their variance specifications.
 5558    /// "context == Co" says that "type" is allowed to vary in the positive direction.
 5559    /// "context == Contra" says that "type" is allowed to vary in the negative direction.
 5560    /// "context == Non" says that "type" must not vary at all.
 5561    /// * "lax" says that the context is not strict -- type parameters declared to be strict must not be used in a lax c
 5562    /// </summary>
 9065563    public void CheckVariance(Type type, ICallable enclosingTypeDefinition, TypeParameter.TPVariance context, bool lax) 
 5564      Contract.Requires(type != null);
 5565      Contract.Requires(enclosingTypeDefinition != null);
 5566
 9065567      type = type.Normalize();  // we keep constraints, since subset types have their own type-parameter variance specif
 11265568      if (type is BasicType) {
 5569        // fine
 9065570      } else if (type is MapType) {
 05571        var t = (MapType)type;
 5572        // If its an infinite map, the domain's context is lax
 05573        CheckVariance(t.Domain, enclosingTypeDefinition, context, lax || !t.Finite);
 05574        CheckVariance(t.Range, enclosingTypeDefinition, context, lax);
 6965575      } else if (type is SetType) {
 105576        var t = (SetType)type;
 5577        // If its an infinite set, the argument's context is lax
 105578        CheckVariance(t.Arg, enclosingTypeDefinition, context, lax || !t.Finite);
 7065579      } else if (type is CollectionType) {
 205580        var t = (CollectionType)type;
 205581        CheckVariance(t.Arg, enclosingTypeDefinition, context, lax);
 13325582      } else if (type is UserDefinedType) {
 6565583        var t = (UserDefinedType)type;
 10385584        if (t.ResolvedClass is TypeParameter tp) {
 3825585          if (tp.Variance != TypeParameter.TPVariance.Non && tp.Variance != context) {
 05586            reporter.Error(MessageSource.Resolver, t.tok, "formal type parameter '{0}' is not used according to its vari
 3825587          } else if (tp.StrictVariance && lax) {
 5588            string hint;
 05589            if (tp.VarianceSyntax == TypeParameter.TPVarianceSyntax.NonVariant_Strict) {
 05590              hint = string.Format(" (perhaps try declaring '{0}' as '-{0}' or '!{0}')", tp.Name);
 05591            } else {
 05592              Contract.Assert(tp.VarianceSyntax == TypeParameter.TPVarianceSyntax.Covariant_Strict);
 05593              hint = string.Format(" (perhaps try changing the declaration from '+{0}' to '*{0}')", tp.Name);
 05594            }
 05595            reporter.Error(MessageSource.Resolver, t.tok, "formal type parameter '{0}' is not used according to its vari
 05596          }
 6565597        } else {
 2745598          var resolvedClass = t.ResolvedClass;
 2745599          Contract.Assert(resolvedClass != null);  // follows from that the given type was successfully resolved
 2745600          Contract.Assert(resolvedClass.TypeArgs.Count == t.TypeArgs.Count);
 2745601          if (lax) {
 5602            // we have to be careful about uses of the type being defined
 05603            var cg = enclosingTypeDefinition.EnclosingModule.CallGraph;
 05604            var t0 = resolvedClass as ICallable;
 05605            if (t0 != null && cg.GetSCCRepresentative(t0) == cg.GetSCCRepresentative(enclosingTypeDefinition)) {
 05606              reporter.Error(MessageSource.Resolver, t.tok, "using the type being defined ('{0}') here would cause a log
 05607            }
 05608          }
 9745609          for (int i = 0; i < t.TypeArgs.Count; i++) {
 1425610            Type p = t.TypeArgs[i];
 1425611            var tpFormal = resolvedClass.TypeArgs[i];
 1425612            CheckVariance(p, enclosingTypeDefinition,
 1425613              context == TypeParameter.TPVariance.Non ? context :
 1425614              context == TypeParameter.TPVariance.Co ? tpFormal.Variance :
 1425615              TypeParameter.Negate(tpFormal.Variance),
 1425616              lax || !tpFormal.StrictVariance);
 1425617          }
 2745618        }
 6565619      } else {
 05620        Contract.Assert(false); throw new cce.UnreachableException();  // unexpected type
 5621      }
 9065622    }
 5623
 5624    /// <summary>
 5625    /// See ConstrainToIntegerType description for the overload above.
 5626    /// </summary>
 148945627    void ConstrainToIntegerType(IToken tok, Type type, bool allowBitVector, TypeConstraint.ErrorMsg errorMsg) {
 5628      Contract.Requires(tok != null);
 5629      Contract.Requires(type != null);
 5630      Contract.Requires(errorMsg != null);
 5631      // We do two constraints: the first can aid in determining types, but allows bit-vectors; the second excludes bit-
 5632      // However, we reuse the error message, so that only one error gets reported.
 148945633      ConstrainSubtypeRelation(new IntVarietiesSupertype(), type, errorMsg);
 187295634      if (!allowBitVector) {
 38355635        AddXConstraint(tok, "IntegerType", type, errorMsg);
 38355636      }
 148945637    }
 5638
 5639    /// <summary>
 5640    /// Attempts to rewrite a datatype update into more primitive operations, after doing the appropriate resolution che
 5641    /// Upon success, returns that rewritten expression and sets "legalSourceConstructors".
 5642    /// Upon some resolution error, return null.
 5643    ///
 5644    /// Actually, the method returns two expressions (or returns "(null, null)"). The first expression is the desugaring
 5645    /// used when the DatatypeUpdateExpr is used in a ghost context. The second is to be used for a compiled context. In
 5646    /// case, "legalSourceConstructors" contains both ghost and compiled constructors.
 5647    ///
 5648    /// The reason for computing both desugarings here is that it's too early to tell if the DatatypeUpdateExpr is being
 5649    /// a ghost or compiled context. This is a consequence of doing the deguaring so early. But it's also convenient to 
 5650    /// desugaring during resolution, because then the desugaring can be constructed as a non-resolved expression on whi
 5651    /// is called--this is easier than constructing an already-resolved expression.
 5652    /// </summary>
 5653    (Expression, Expression) ResolveDatatypeUpdate(IToken tok, Expression root, DatatypeDecl dt, List<Tuple<IToken, stri
 05654      ResolutionContext resolutionContext, out List<MemberDecl> members, out List<DatatypeCtor> legalSourceConstructors)
 5655      Contract.Requires(tok != null);
 5656      Contract.Requires(root != null);
 5657      Contract.Requires(dt != null);
 5658      Contract.Requires(memberUpdates != null);
 5659      Contract.Requires(resolutionContext != null);
 5660
 05661      legalSourceConstructors = null;
 05662      members = new List<MemberDecl>();
 5663
 5664      // First, compute the list of candidate result constructors, that is, the constructors
 5665      // that have all of the mentioned destructors. Issue errors for duplicated names and for
 5666      // names that are not destructors in the datatype.
 05667      var candidateResultCtors = dt.Ctors;  // list of constructors that have all the so-far-mentioned destructors
 05668      var memberNames = new HashSet<string>();
 05669      var rhsBindings = new Dictionary<string, Tuple<BoundVar/*let variable*/, IdentifierExpr/*id expr for let variable*
 05670      var subst = TypeParameter.SubstitutionMap(dt.TypeArgs, root.Type.NormalizeExpand().TypeArgs);
 05671      foreach (var entry in memberUpdates) {
 05672        var destructor_str = entry.Item2;
 05673        if (memberNames.Contains(destructor_str)) {
 05674          reporter.Error(MessageSource.Resolver, entry.Item1, "duplicate update member '{0}'", destructor_str);
 05675        } else {
 05676          memberNames.Add(destructor_str);
 05677          if (!classMembers[dt].TryGetValue(destructor_str, out var member)) {
 05678            reporter.Error(MessageSource.Resolver, entry.Item1, "member '{0}' does not exist in datatype '{1}'", destruc
 05679          } else if (!(member is DatatypeDestructor)) {
 05680            reporter.Error(MessageSource.Resolver, entry.Item1, "member '{0}' is not a destructor in datatype '{1}'", de
 05681          } else {
 05682            members.Add(member);
 05683            var destructor = (DatatypeDestructor)member;
 05684            var intersection = new List<DatatypeCtor>(candidateResultCtors.Intersect(destructor.EnclosingCtors));
 05685            if (intersection.Count == 0) {
 05686              reporter.Error(MessageSource.Resolver, entry.Item1,
 05687                "updated datatype members must belong to the same constructor (unlike the previously mentioned destructo
 05688                destructor_str, DatatypeDestructor.PrintableCtorNameList(candidateResultCtors, "or"));
 05689            } else {
 05690              candidateResultCtors = intersection;
 05691              if (destructor.IsGhost) {
 05692                rhsBindings.Add(destructor_str, new Tuple<BoundVar, IdentifierExpr, Expression>(null, null, entry.Item3)
 05693              } else {
 05694                var xName = FreshTempVarName(string.Format("dt_update#{0}#", destructor_str), resolutionContext.CodeCont
 05695                var xVar = new BoundVar(new AutoGeneratedToken(tok), xName, destructor.Type.Subst(subst));
 05696                var x = new IdentifierExpr(new AutoGeneratedToken(tok), xVar);
 05697                rhsBindings.Add(destructor_str, new Tuple<BoundVar, IdentifierExpr, Expression>(xVar, x, entry.Item3));
 05698              }
 05699            }
 05700          }
 05701        }
 05702      }
 05703      if (candidateResultCtors.Count == 0) {
 05704        return (null, null);
 5705      }
 5706
 5707      // Check that every candidate result constructor has given a name to all of its parameters.
 05708      var hasError = false;
 05709      foreach (var ctor in candidateResultCtors) {
 05710        if (ctor.Formals.Exists(f => !f.HasName)) {
 05711          reporter.Error(MessageSource.Resolver, tok,
 05712            "candidate result constructor '{0}' has an anonymous parameter (to use in datatype update expression, name a
 05713            ctor.Name);
 05714          hasError = true;
 05715        }
 05716      }
 05717      if (hasError) {
 05718        return (null, null);
 5719      }
 5720
 5721      // The legal source constructors are the candidate result constructors. (Yep, two names for the same thing.)
 05722      legalSourceConstructors = candidateResultCtors;
 05723      Contract.Assert(1 <= legalSourceConstructors.Count);
 5724
 05725      var desugaringForGhostContext = DesugarDatatypeUpdate(tok, root, dt, candidateResultCtors, rhsBindings, resolution
 05726      var nonGhostConstructors = candidateResultCtors.Where(ctor => !ctor.IsGhost).ToList();
 05727      if (nonGhostConstructors.Count == candidateResultCtors.Count) {
 05728        return (desugaringForGhostContext, desugaringForGhostContext);
 5729      }
 05730      var desugaringForCompiledContext = DesugarDatatypeUpdate(tok, root, dt, nonGhostConstructors, rhsBindings, resolut
 05731      return (desugaringForGhostContext, desugaringForCompiledContext);
 05732    }
 5733
 5734    /// <summary>
 5735    // Rewrite the datatype update root.(x := X, y := Y, ...) to:
 5736    ///     var d := root;
 5737    ///     var x := X;  // EXCEPT: don't do this for ghost fields
 5738    ///     var y := Y;
 5739    ///     ..
 5740    ///     if d.CandidateResultConstructor0 then
 5741    ///       CandidateResultConstructor0(x, y, ..., d.f0, d.f1, ...)  // for a ghost field x, use the expression X dire
 5742    ///     else if d.CandidateResultConstructor1 then
 5743    ///       CandidateResultConstructor0(x, y, ..., d.g0, d.g1, ...)
 5744    ///     ...
 5745    ///     else
 5746    ///       CandidateResultConstructorN(x, y, ..., d.k0, d.k1, ...)
 5747    /// </summary>
 5748    private Expression DesugarDatatypeUpdate(IToken tok, Expression root, DatatypeDecl dt, List<DatatypeCtor> candidateR
 05749      Dictionary<string, Tuple<BoundVar, IdentifierExpr, Expression>> rhsBindings, ResolutionContext resolutionContext) 
 5750
 05751      if (candidateResultCtors.Count == 0) {
 05752        return root;
 5753      }
 05754      Expression rewrite = null;
 5755      // Create a unique name for d', the variable we introduce in the let expression
 05756      var dName = FreshTempVarName("dt_update_tmp#", resolutionContext.CodeContext);
 05757      var dVar = new BoundVar(new AutoGeneratedToken(tok), dName, root.Type);
 05758      var d = new IdentifierExpr(new AutoGeneratedToken(tok), dVar);
 05759      Expression body = null;
 05760      candidateResultCtors.Reverse();
 05761      foreach (var crc in candidateResultCtors) {
 5762        // Build the arguments to the datatype constructor, using the updated value in the appropriate slot
 05763        var ctorArguments = new List<Expression>();
 05764        var actualBindings = new List<ActualBinding>();
 05765        foreach (var f in crc.Formals) {
 5766          Expression ctorArg;
 05767          if (rhsBindings.TryGetValue(f.Name, out var info)) {
 05768            ctorArg = info.Item2 ?? info.Item3;
 05769          } else {
 05770            ctorArg = new ExprDotName(tok, d, f.Name, null);
 05771          }
 05772          ctorArguments.Add(ctorArg);
 05773          var bindingName = new Token(tok.line, tok.col) {
 05774            Uri = tok.Uri,
 05775            val = f.Name
 05776          };
 05777          actualBindings.Add(new ActualBinding(bindingName, ctorArg));
 05778        }
 05779        var ctor_call = new DatatypeValue(tok, crc.EnclosingDatatype.Name, crc.Name, actualBindings);
 5780        // in the following line, resolve to root.Type, so that type parameters get filled in appropriately
 05781        ResolveDatatypeValue(resolutionContext, ctor_call, dt, root.Type.NormalizeExpand());
 5782
 05783        if (body == null) {
 05784          body = ctor_call;
 05785        } else {
 5786          // body = if d.crc? then ctor_call else body
 05787          var guard = new ExprDotName(tok, d, crc.QueryField.Name, null);
 05788          body = new ITEExpr(tok, false, guard, ctor_call, body);
 05789        }
 05790      }
 05791      Contract.Assert(body != null); // because there was at least one element in candidateResultCtors
 5792
 5793      // Wrap the let's around body
 05794      rewrite = body;
 05795      foreach (var entry in rhsBindings) {
 05796        if (entry.Value.Item1 != null) {
 05797          var lhs = new CasePattern<BoundVar>(tok, entry.Value.Item1);
 05798          rewrite = new LetExpr(tok, new List<CasePattern<BoundVar>>() { lhs }, new List<Expression>() { entry.Value.Ite
 05799        }
 05800      }
 05801      var dVarPat = new CasePattern<BoundVar>(tok, dVar);
 05802      rewrite = new LetExpr(tok, new List<CasePattern<BoundVar>>() { dVarPat }, new List<Expression>() { root }, rewrite
 05803      Contract.Assert(rewrite != null);
 05804      ResolveExpression(rewrite, resolutionContext);
 05805      return rewrite;
 05806    }
 5807
 5808    public Expression ResolveNameSegment(NameSegment expr, bool isLastNameSegment, List<ActualBinding> args,
 1324035809      ResolutionContext resolutionContext, bool allowMethodCall, bool complain = true) {
 1324035810      return ResolveNameSegment(expr, isLastNameSegment, args, resolutionContext, allowMethodCall, complain, out _);
 1324035811    }
 5812
 5813    /// <summary>
 5814    /// Look up expr.Name in the following order:
 5815    ///  0. Local variable, parameter, or bound variable.
 5816    ///     (Language design note:  If this clashes with something of interest, one can always rename the local variable
 5817    ///  1. Member of enclosing class (an implicit "this" is inserted, if needed)
 5818    ///  2. If isLastNameSegment:
 5819    ///     Unambiguous constructor name of a datatype in the enclosing module (if two constructors have the same name, 
 5820    ///     (Language design note:  If the constructor name is ambiguous or if one of the steps above takes priority, on
 5821    ///  3. Member of the enclosing module (type name or the name of a module)
 5822    ///  4. Static function or method in the enclosing module or its imports
 5823    ///  5. If !isLastNameSegment:
 5824    ///     Unambiguous constructor name of a datatype in the enclosing module
 5825    ///
 5826    /// </summary>
 5827    /// <param name="expr"></param>
 5828    /// <param name="isLastNameSegment">Indicates that the NameSegment is not directly enclosed in another NameSegment o
 5829    /// <param name="args">If the NameSegment is enclosed in an ApplySuffix, then these are the arguments.  The method r
 5830    /// that these arguments, if any, were not used.  If args is non-null and the method does use them, the method retur
 5831    /// that incorporates these arguments.</param>
 5832    /// <param name="resolutionContext"></param>
 5833    /// <param name="allowMethodCall">If false, generates an error if the name denotes a method. If true and the name de
 5834    /// a MemberSelectExpr whose .Member is a Method.</param>
 5835    /// <param name="shadowedModule">If the name being resolved shadows an imported module, then that module is reported
 5836    /// through this parameter.  This happens when module <c>Option</c> in <c>import opened Option</c> also contains a
 5837    /// <c>datatype Option</c>, in which case <c>Option</c> refers to the datatype, not the module
 5838    /// (https://github.com/dafny-lang/dafny/issues/1996).</param>
 1393875839    Expression ResolveNameSegment(NameSegment expr, bool isLastNameSegment, List<ActualBinding> args, ResolutionContext 
 5840      Contract.Requires(expr != null);
 5841      Contract.Requires(!expr.WasResolved());
 5842      Contract.Requires(resolutionContext != null);
 5843      Contract.Ensures(Contract.Result<Expression>() == null || args != null);
 5844
 1393875845      shadowedModule = null;
 5846
 1393875847      if (expr.OptTypeArguments != null) {
 05848        foreach (var ty in expr.OptTypeArguments) {
 05849          ResolveType(expr.tok, ty, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 05850        }
 05851      }
 5852
 1393875853      Expression r = null;  // the resolved expression, if successful
 1393875854      Expression rWithArgs = null;  // the resolved expression after incorporating "args"
 5855
 5856      // For 0:
 5857      IVariable v;
 5858      // For 1:
 5859      // For 1 and 4:
 1393875860      MemberDecl member = null;
 5861      // For 2 and 5:
 5862      // For 3:
 5863
 1393875864      var name = resolutionContext.InReveal ? "reveal_" + expr.Name : expr.Name;
 1393875865      v = scope.Find(name);
 2694895866      if (v != null) {
 5867        // ----- 0. local variable, parameter, or bound variable
 1301025868        if (expr.OptTypeArguments != null) {
 05869          if (complain) {
 05870            reporter.Error(MessageSource.Resolver, expr.tok, "variable '{0}' does not take any type parameters", name);
 05871          } else {
 05872            expr.ResolvedExpression = null;
 05873            return null;
 5874          }
 05875        }
 1301025876        r = new IdentifierExpr(expr.tok, v);
 1428585877      } else if (currentClass is TopLevelDeclWithMembers cl && classMembers.TryGetValue(cl, out var members) && members.
 5878        // ----- 1. member of the enclosing class
 5879        Expression receiver;
 69425880        if (member.IsStatic) {
 34715881          receiver = new StaticReceiverExpr(expr.tok, UserDefinedType.FromTopLevelDecl(expr.tok, currentClass, currentCl
 34715882        } else {
 05883          if (!scope.AllowInstance) {
 05884            if (complain) {
 05885              reporter.Error(MessageSource.Resolver, expr.tok, "'this' is not allowed in a 'static' context"); //TODO: R
 05886            } else {
 05887              expr.ResolvedExpression = null;
 05888              return null;
 5889            }
 5890            // nevertheless, set "receiver" to a value so we can continue resolution
 05891          }
 05892          receiver = new ImplicitThisExpr(expr.tok);
 05893          receiver.Type = GetThisType(expr.tok, currentClass);  // resolve here
 05894        }
 34715895        r = ResolveExprDotCall(expr.tok, receiver, null, member, args, expr.OptTypeArguments, resolutionContext, allowMe
 150895896      } else if (isLastNameSegment && moduleInfo.Ctors.TryGetValue(name, out var pair)) {
 5897        // ----- 2. datatype constructor
 58045898        if (ResolveDatatypeConstructor(expr, args, resolutionContext, complain, pair, name, ref r, ref rWithArgs)) {
 05899          return null;
 5900        }
 58245901      } else if (moduleInfo.TopLevels.TryGetValue(name, out var decl)) {
 5902        // ----- 3. Member of the enclosing module
 5903
 5904        // Record which imported module, if any, was shadowed by `name` in the current module.
 105905        shadowedModule = moduleInfo.ShadowedImportedModules.GetValueOrDefault(name);
 5906
 105907        if (decl is AmbiguousTopLevelDecl) {
 05908          var ad = (AmbiguousTopLevelDecl)decl;
 05909          if (complain) {
 05910            reporter.Error(MessageSource.Resolver, expr.tok, "The name {0} ambiguously refers to a type in one of the mo
 05911          } else {
 05912            expr.ResolvedExpression = null;
 05913            return null;
 5914          }
 105915        } else {
 5916          // We have found a module name or a type name, neither of which is an expression. However, the NameSegment we'
 5917          // looking at may be followed by a further suffix that makes this into an expresion. We postpone the rest of t
 5918          // resolution to any such suffix. For now, we create a temporary expression that will never be seen by the com
 5919          // or verifier, just to have a placeholder where we can recorded what we have found.
 205920          if (!isLastNameSegment) {
 105921            if (decl is ClassDecl cd && cd.NonNullTypeDecl != null && name != cd.NonNullTypeDecl.Name) {
 5922              // A possibly-null type C? was mentioned. But it does not have any further members. The program should hav
 5923              // the name of the class, C. Report an error and continue.
 05924              if (complain) {
 05925                reporter.Error(MessageSource.Resolver, expr.tok, "To access members of {0} '{1}', write '{1}', not '{2}'
 05926              } else {
 05927                expr.ResolvedExpression = null;
 05928                return null;
 5929              }
 05930            }
 105931          }
 105932          r = CreateResolver_IdentifierExpr(expr.tok, name, expr.OptTypeArguments, decl);
 105933        }
 5934
 105935      } else if (moduleInfo.StaticMembers.TryGetValue(name, out member)) {
 5936        // ----- 4. static member of the enclosing module
 05937        Contract.Assert(member.IsStatic); // moduleInfo.StaticMembers is supposed to contain only static members of the 
 05938        if (member is AmbiguousMemberDecl) {
 05939          var ambiguousMember = (AmbiguousMemberDecl)member;
 05940          if (complain) {
 05941            reporter.Error(MessageSource.Resolver, expr.tok, "The name {0} ambiguously refers to a static member in one 
 05942          } else {
 05943            expr.ResolvedExpression = null;
 05944            return null;
 5945          }
 05946        } else {
 05947          var receiver = new StaticReceiverExpr(expr.tok, (ClassDecl)member.EnclosingClass, true);
 05948          r = ResolveExprDotCall(expr.tok, receiver, null, member, args, expr.OptTypeArguments, resolutionContext, allow
 05949        }
 5950
 05951      } else if (!isLastNameSegment && moduleInfo.Ctors.TryGetValue(name, out pair)) {
 5952        // ----- 5. datatype constructor
 05953        if (ResolveDatatypeConstructor(expr, args, resolutionContext, complain, pair, name, ref r, ref rWithArgs)) {
 05954          return null;
 5955        }
 5956
 05957      } else {
 5958        // ----- None of the above
 05959        if (complain) {
 05960          if (resolutionContext.InReveal) {
 05961            reporter.Error(MessageSource.Resolver, expr.tok, "cannot reveal '{0}' because no constant, assert label, or 
 05962          } else {
 05963            reporter.Error(MessageSource.Resolver, expr.tok, "unresolved identifier: {0}", name);
 05964          }
 05965        } else {
 05966          expr.ResolvedExpression = null;
 05967          return null;
 5968        }
 05969      }
 5970
 1393875971      if (r == null) {
 5972        // an error has been reported above; we won't fill in .ResolvedExpression, but we still must fill in .Type
 05973        expr.Type = new InferredTypeProxy();
 1393875974      } else {
 1393875975        expr.ResolvedExpression = r;
 1393875976        var rt = r.Type;
 1393875977        var nt = rt.UseInternalSynonym();
 1393875978        expr.Type = nt;
 1393875979      }
 1393875980      return rWithArgs;
 1393875981    }
 5982
 58045983    private bool ResolveDatatypeConstructor(NameSegment expr, List<ActualBinding>/*?*/ args, ResolutionContext resolutio
 5984      Contract.Requires(expr != null);
 5985      Contract.Requires(resolutionContext != null);
 5986
 58045987      if (pair.Item2) {
 5988        // there is more than one constructor with this name
 05989        if (complain) {
 05990          reporter.Error(MessageSource.Resolver, expr.tok, "the name '{0}' denotes a datatype constructor, but does not 
 05991            pair.Item1.EnclosingDatatype.Name);
 05992        } else {
 05993          expr.ResolvedExpression = null;
 05994          return true;
 5995        }
 58045996      } else {
 58045997        if (expr.OptTypeArguments != null) {
 05998          if (complain) {
 05999            reporter.Error(MessageSource.Resolver, expr.tok, "datatype constructor does not take any type parameters ('{
 06000          } else {
 06001            expr.ResolvedExpression = null;
 06002            return true;
 6003          }
 06004        }
 58046005        var rr = new DatatypeValue(expr.tok, pair.Item1.EnclosingDatatype.Name, name, args ?? new List<ActualBinding>())
 58046006        bool ok = ResolveDatatypeValue(resolutionContext, rr, pair.Item1.EnclosingDatatype, null, complain);
 58046007        if (!ok) {
 06008          expr.ResolvedExpression = null;
 06009          return true;
 6010        }
 92286011        if (args == null) {
 34246012          r = rr;
 58046013        } else {
 23806014          r = rr; // this doesn't really matter, since we're returning an "rWithArgs" (but if would have been proper to 
 23806015          rWithArgs = rr;
 23806016        }
 58046017      }
 58046018      return false;
 58046019    }
 6020
 6021    /// <summary>
 6022    /// Look up expr.Name in the following order:
 6023    ///  0. Type parameter
 6024    ///  1. Member of enclosing class (an implicit "this" is inserted, if needed)
 6025    ///  2. Member of the enclosing module (type name or the name of a module)
 6026    ///  3. Static function or method in the enclosing module or its imports
 6027    ///
 6028    /// Note: 1 and 3 are not used now, but they will be of interest when async task types are supported.
 6029    /// </summary>
 945126030    void ResolveNameSegment_Type(NameSegment expr, ResolutionContext resolutionContext, ResolveTypeOption option, List<T
 6031      Contract.Requires(expr != null);
 6032      Contract.Requires(!expr.WasResolved());
 6033      Contract.Requires(resolutionContext != null);
 6034      Contract.Requires((option.Opt == ResolveTypeOptionEnum.DontInfer || option.Opt == ResolveTypeOptionEnum.InferTypeP
 6035
 1173806036      if (expr.OptTypeArguments != null) {
 1859166037        foreach (var ty in expr.OptTypeArguments) {
 391046038          ResolveType(expr.tok, ty, resolutionContext, option, defaultTypeArguments);
 391046039        }
 228686040      }
 6041
 945126042      Expression r = null;  // the resolved expression, if successful
 6043
 6044      // For 0:
 6045      TypeParameter tp;
 6046#if ASYNC_TASK_TYPES
 6047      // For 1:
 6048      Dictionary<string, MemberDecl> members;
 6049      // For 1 and 3:
 6050      MemberDecl member = null;
 6051#endif
 6052      // For 2:
 6053
 945126054      tp = allTypeParameters.Find(expr.Name);
 950466055      if (tp != null) {
 6056        // ----- 0. type parameter
 10686057        if (expr.OptTypeArguments == null) {
 5346058          r = new Resolver_IdentifierExpr(expr.tok, tp);
 5346059        } else {
 06060          reporter.Error(MessageSource.Resolver, expr.tok, "Type parameter expects no type arguments: {0}", expr.Name);
 06061        }
 6062#if ASYNC_TASK_TYPES  // At the moment, there is no way for a class member to part of a type name, but this changes with
 6063      } else if (currentClass != null && classMembers.TryGetValue(currentClass, out members) && members.TryGetValue(expr
 6064        // ----- 1. member of the enclosing class
 6065        Expression receiver;
 6066        if (member.IsStatic) {
 6067          receiver = new StaticReceiverExpr(expr.tok, (ClassDecl)member.EnclosingClass);
 6068        } else {
 6069          if (!scope.AllowInstance) {
 6070            reporter.Error(MessageSource.Resolver, expr.tok, "'this' is not allowed in a 'static' context");
 6071            // nevertheless, set "receiver" to a value so we can continue resolution
 6072          }
 6073          receiver = new ImplicitThisExpr(expr.tok);
 6074          receiver.Type = GetThisType(expr.tok, (ClassDecl)member.EnclosingClass);  // resolve here
 6075        }
 6076        r = ResolveExprDotCall(expr.tok, receiver, member, expr.OptTypeArguments, opts.resolutionContext, allowMethodCal
 6077#endif
 1884906078      } else if (moduleInfo.TopLevels.TryGetValue(expr.Name, out var decl)) {
 6079        // ----- 2. Member of the enclosing module
 939786080        if (decl is AmbiguousTopLevelDecl) {
 06081          var ad = (AmbiguousTopLevelDecl)decl;
 06082          reporter.Error(MessageSource.Resolver, expr.tok, "The name {0} ambiguously refers to a type in one of the modu
 939786083        } else {
 6084          // We have found a module name or a type name, neither of which is a type expression. However, the NameSegment
 6085          // looking at may be followed by a further suffix that makes this into a type expresion. We postpone the rest 
 6086          // resolution to any such suffix. For now, we create a temporary expression that will never be seen by the com
 6087          // or verifier, just to have a placeholder where we can recorded what we have found.
 939786088          r = CreateResolver_IdentifierExpr(expr.tok, expr.Name, expr.OptTypeArguments, decl);
 939786089        }
 6090
 6091#if ASYNC_TASK_TYPES  // At the moment, there is no way for a class member to part of a type name, but this changes with
 6092      } else if (moduleInfo.StaticMembers.TryGetValue(expr.Name, out member)) {
 6093        // ----- 3. static member of the enclosing module
 6094        Contract.Assert(member.IsStatic); // moduleInfo.StaticMembers is supposed to contain only static members of the 
 6095        if (ReallyAmbiguousThing(ref member)) {
 6096          reporter.Error(MessageSource.Resolver, expr.tok, "The name {0} ambiguously refers to a static member in one of
 6097        } else {
 6098          var receiver = new StaticReceiverExpr(expr.tok, (ClassDecl)member.EnclosingClass);
 6099          r = ResolveExprDotCall(expr.tok, receiver, member, expr.OptTypeArguments, opts.resolutionContext, allowMethodC
 6100        }
 6101#endif
 939786102      } else {
 6103        // ----- None of the above
 06104        reporter.Error(MessageSource.Resolver, expr.tok, "Type or type parameter is not declared in this scope: {0} (did
 06105      }
 6106
 945126107      if (r == null) {
 6108        // an error has been reported above; we won't fill in .ResolvedExpression, but we still must fill in .Type
 06109        expr.Type = new InferredTypeProxy();
 945126110      } else {
 945126111        expr.ResolvedExpression = r;
 945126112        expr.Type = r.Type;
 945126113      }
 945126114    }
 6115
 6116    /// <summary>
 6117    /// To resolve "id" in expression "E . id", do:
 6118    ///  * If E denotes a module name M:
 6119    ///      0. If isLastNameSegment:
 6120    ///         Unambiguous constructor name of a datatype in module M (if two constructors have the same name, an error
 6121    ///         (Language design note:  If the constructor name is ambiguous or if one of the steps above takes priority
 6122    ///      1. Member of module M:  sub-module (including submodules of imports), class, datatype, etc.
 6123    ///         (if two imported types have the same name, an error message is produced here)
 6124    ///      2. Static function or method of M._default
 6125    ///    (Note that in contrast to ResolveNameSegment, imported modules, etc. are ignored)
 6126    ///  * If E denotes a type:
 6127    ///      3. Look up id as a member of that type
 6128    ///  * If E denotes an expression:
 6129    ///      4. Let T be the type of E.  Look up id in T.
 6130    /// </summary>
 6131    /// <param name="expr"></param>
 6132    /// <param name="isLastNameSegment">Indicates that the ExprDotName is not directly enclosed in another ExprDotName e
 6133    /// <param name="args">If the ExprDotName is enclosed in an ApplySuffix, then these are the arguments.  The method r
 6134    /// that these arguments, if any, were not used.  If args is non-null and the method does use them, the method retur
 6135    /// that incorporates these arguments.</param>
 6136    /// <param name="resolutionContext"></param>
 6137    /// <param name="allowMethodCall">If false, generates an error if the name denotes a method. If true and the name de
 6138    /// a Resolver_MethodCall.</param>
 78346139    Expression ResolveDotSuffix(ExprDotName expr, bool isLastNameSegment, List<ActualBinding> args, ResolutionContext re
 6140      Contract.Requires(expr != null);
 6141      Contract.Requires(!expr.WasResolved());
 6142      Contract.Requires(resolutionContext != null);
 6143      Contract.Ensures(Contract.Result<Expression>() == null || args != null);
 6144
 6145      // resolve the LHS expression
 6146      // LHS should not be reveal lemma
 78346147      ModuleDecl shadowedImport = null;
 78346148      ResolutionContext nonRevealOpts = resolutionContext with { InReveal = false };
 148186149      if (expr.Lhs is NameSegment) {
 69846150        ResolveNameSegment((NameSegment)expr.Lhs, false, null, nonRevealOpts, false, true, out shadowedImport);
 78346151      } else if (expr.Lhs is ExprDotName) {
 06152        ResolveDotSuffix((ExprDotName)expr.Lhs, false, null, nonRevealOpts, false);
 8506153      } else {
 8506154        ResolveExpression(expr.Lhs, nonRevealOpts);
 8506155      }
 6156
 78346157      if (expr.OptTypeArguments != null) {
 06158        foreach (var ty in expr.OptTypeArguments) {
 06159          ResolveType(expr.tok, ty, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 06160        }
 06161      }
 6162
 78346163      Expression r = null;  // the resolved expression, if successful
 78346164      Expression rWithArgs = null;  // the resolved expression after incorporating "args"
 78346165      MemberDecl member = null;
 6166
 78346167      var name = resolutionContext.InReveal ? "reveal_" + expr.SuffixName : expr.SuffixName;
 78346168      if (!expr.Lhs.WasResolved()) {
 06169        return null;
 6170      }
 78346171      var lhs = expr.Lhs.Resolved;
 78346172      if (lhs != null && lhs.Type is Resolver_IdentifierExpr.ResolverType_Module) {
 06173        var ri = (Resolver_IdentifierExpr)lhs;
 06174        var sig = ((ModuleDecl)ri.Decl).AccessibleSignature(useCompileSignatures);
 06175        sig = GetSignature(sig);
 6176        // For 0:
 6177        // For 1:
 6178
 06179        if (isLastNameSegment && sig.Ctors.TryGetValue(name, out var pair)) {
 6180          // ----- 0. datatype constructor
 06181          if (pair.Item2) {
 6182            // there is more than one constructor with this name
 06183            reporter.Error(MessageSource.Resolver, expr.tok, "the name '{0}' denotes a datatype constructor in module {2
 06184          } else {
 06185            if (expr.OptTypeArguments != null) {
 06186              reporter.Error(MessageSource.Resolver, expr.tok, "datatype constructor does not take any type parameters (
 06187            }
 06188            var rr = new DatatypeValue(expr.tok, pair.Item1.EnclosingDatatype.Name, name, args ?? new List<ActualBinding
 06189            ResolveDatatypeValue(resolutionContext, rr, pair.Item1.EnclosingDatatype, null);
 6190
 06191            if (args == null) {
 06192              r = rr;
 06193            } else {
 06194              r = rr;  // this doesn't really matter, since we're returning an "rWithArgs" (but if would have been prope
 06195              rWithArgs = rr;
 06196            }
 06197          }
 06198        } else if (sig.TopLevels.TryGetValue(name, out var decl)) {
 6199          // ----- 1. Member of the specified module
 06200          if (decl is AmbiguousTopLevelDecl) {
 06201            var ad = (AmbiguousTopLevelDecl)decl;
 06202            reporter.Error(MessageSource.Resolver, expr.tok, "The name {0} ambiguously refers to a type in one of the mo
 06203          } else {
 6204            // We have found a module name or a type name, neither of which is an expression. However, the ExprDotName w
 6205            // looking at may be followed by a further suffix that makes this into an expresion. We postpone the rest of
 6206            // resolution to any such suffix. For now, we create a temporary expression that will never be seen by the c
 6207            // or verifier, just to have a placeholder where we can recorded what we have found.
 06208            if (!isLastNameSegment) {
 06209              if (decl is ClassDecl cd && cd.NonNullTypeDecl != null && name != cd.NonNullTypeDecl.Name) {
 6210                // A possibly-null type C? was mentioned. But it does not have any further members. The program should h
 6211                // the name of the class, C. Report an error and continue.
 06212                reporter.Error(MessageSource.Resolver, expr.tok, "To access members of {0} '{1}', write '{1}', not '{2}'
 06213              }
 06214            }
 06215            r = CreateResolver_IdentifierExpr(expr.tok, name, expr.OptTypeArguments, decl);
 06216          }
 06217        } else if (sig.StaticMembers.TryGetValue(name, out member)) {
 6218          // ----- 2. static member of the specified module
 06219          Contract.Assert(member.IsStatic); // moduleInfo.StaticMembers is supposed to contain only static members of th
 06220          if (member is AmbiguousMemberDecl) {
 06221            var ambiguousMember = (AmbiguousMemberDecl)member;
 06222            reporter.Error(MessageSource.Resolver, expr.tok, "The name {0} ambiguously refers to a static member in one 
 06223          } else {
 06224            var receiver = new StaticReceiverExpr(expr.Lhs.tok, (ClassDecl)member.EnclosingClass, false);
 06225            receiver.ContainerExpression = expr.Lhs;
 06226            r = ResolveExprDotCall(expr.tok, receiver, null, member, args, expr.OptTypeArguments, resolutionContext, all
 06227          }
 06228        } else {
 06229          reporter.Error(MessageSource.Resolver, expr.tok, "unresolved identifier: {0}", name);
 06230        }
 6231
 78446232      } else if (lhs != null && lhs.Type is Resolver_IdentifierExpr.ResolverType_Type) {
 106233        var ri = (Resolver_IdentifierExpr)lhs;
 6234        // ----- 3. Look up name in type
 6235        // expand any synonyms
 106236        var ty = new UserDefinedType(expr.tok, ri.Decl.Name, ri.Decl, ri.TypeArgs).NormalizeExpand();
 206237        if (ty.IsDatatype) {
 6238          // ----- LHS is a datatype
 106239          var dt = ty.AsDatatype;
 206240          if (dt.ConstructorsByName != null && dt.ConstructorsByName.TryGetValue(name, out var ctor)) {
 106241            if (expr.OptTypeArguments != null) {
 06242              reporter.Error(MessageSource.Resolver, expr.tok, "datatype constructor does not take any type parameters (
 06243            }
 106244            var rr = new DatatypeValue(expr.tok, ctor.EnclosingDatatype.Name, name, args ?? new List<ActualBinding>());
 106245            ResolveDatatypeValue(resolutionContext, rr, ctor.EnclosingDatatype, ty);
 206246            if (args == null) {
 106247              r = rr;
 106248            } else {
 06249              r = rr;  // this doesn't really matter, since we're returning an "rWithArgs" (but if would have been prope
 06250              rWithArgs = rr;
 06251            }
 106252          }
 106253        }
 106254        var cd = r == null ? ty.AsTopLevelTypeWithMembersBypassInternalSynonym : null;
 106255        if (cd != null) {
 6256          // ----- LHS is a type with members
 06257          if (classMembers.TryGetValue(cd, out var members) && members.TryGetValue(name, out member)) {
 06258            if (!VisibleInScope(member)) {
 06259              reporter.Error(MessageSource.Resolver, expr.tok, "member '{0}' has not been imported in this scope and can
 06260            }
 06261            if (!member.IsStatic) {
 06262              reporter.Error(MessageSource.Resolver, expr.tok, "accessing member '{0}' requires an instance expression",
 6263              // nevertheless, continue creating an expression that approximates a correct one
 06264            }
 06265            var receiver = new StaticReceiverExpr(expr.Lhs.tok, (UserDefinedType)ty.NormalizeExpand(), (TopLevelDeclWith
 06266            receiver.ContainerExpression = expr.Lhs;
 06267            r = ResolveExprDotCall(expr.tok, receiver, null, member, args, expr.OptTypeArguments, resolutionContext, all
 06268          }
 06269        }
 106270        if (r == null) {
 06271          reporter.Error(MessageSource.Resolver, expr.tok, "member '{0}' does not exist in {2} '{1}'", name, ri.Decl.Nam
 06272        }
 156586273      } else if (lhs != null) {
 6274        // ----- 4. Look up name in the type of the Lhs
 78246275        member = ResolveMember(expr.tok, expr.Lhs.Type, name, out var tentativeReceiverType);
 156486276        if (member != null) {
 6277          Expression receiver;
 156486278          if (!member.IsStatic) {
 78246279            receiver = expr.Lhs;
 78246280            AddAssignableConstraint(expr.tok, tentativeReceiverType, receiver.Type, "receiver type ({1}) does not have a
 78246281            r = ResolveExprDotCall(expr.tok, receiver, tentativeReceiverType, member, args, expr.OptTypeArguments, resol
 78246282          } else {
 06283            receiver = new StaticReceiverExpr(expr.tok, (UserDefinedType)tentativeReceiverType, (TopLevelDeclWithMembers
 06284            r = ResolveExprDotCall(expr.tok, receiver, null, member, args, expr.OptTypeArguments, resolutionContext, all
 06285          }
 78246286        }
 78246287      }
 6288
 78346289      if (r == null) {
 6290        // an error has been reported above; we won't fill in .ResolvedExpression, but we still must fill in .Type
 06291        expr.Type = new InferredTypeProxy();
 78346292      } else {
 78346293        CheckForAmbiguityInShadowedImportedModule(shadowedImport, name, expr.tok, useCompileSignatures, isLastNameSegmen
 78346294        expr.ResolvedExpression = r;
 78346295        expr.Type = r.Type;
 78346296      }
 78346297      return rWithArgs;
 78346298    }
 6299
 6300    /// <summary>
 6301    /// Check whether the name we just resolved may have been resolved differently if we didn't allow member `M.M` of
 6302    /// module `M` to shadow `M` when the user writes `import opened M`.  Raising an error in that case allowed us to
 6303    /// change the behavior of `import opened` without silently changing the meaning of existing programs.
 6304    /// (https://github.com/dafny-lang/dafny/issues/1996)
 6305    ///
 6306    /// Note the extra care for the constructor case, which is needed because the constructors of datatype `M.M` are
 6307    /// exposed through both `M` and `M.M`, without ambiguity.
 6308    /// </summary>
 6309    private void CheckForAmbiguityInShadowedImportedModule(ModuleDecl moduleDecl, string name,
 78346310      IToken tok, bool useCompileSignatures, bool isLastNameSegment) {
 78346311      if (moduleDecl != null && NameConflictsWithModuleContents(moduleDecl, name, useCompileSignatures, isLastNameSegmen
 06312        reporter.Error(MessageSource.Resolver, tok,
 06313          "Reference to member '{0}' is ambiguous: name '{1}' shadows an import-opened module of the same name, and "
 06314          + "both have a member '{0}'. To solve this issue, give a different name to the imported module using "
 06315          + "`import opened XYZ = ...` instead of `import opened ...`.",
 06316          name, moduleDecl.Name);
 06317      }
 78346318    }
 6319
 06320    private bool NameConflictsWithModuleContents(ModuleDecl moduleDecl, string name, bool useCompileSignatures, bool isL
 06321      var sig = GetSignature(moduleDecl.AccessibleSignature(useCompileSignatures));
 06322      return (
 06323        (isLastNameSegment
 06324         && sig.Ctors.GetValueOrDefault(name) is { Item1: var constructor, Item2: var ambiguous }
 06325         && !ambiguous && constructor.EnclosingDatatype.Name != moduleDecl.Name)
 06326        || sig.TopLevels.ContainsKey(name)
 06327        || sig.StaticMembers.ContainsKey(name)
 06328      );
 06329    }
 6330
 6331    Expression ResolveExprDotCall(IToken tok, Expression receiver, Type receiverTypeBound/*?*/,
 112956332      MemberDecl member, List<ActualBinding> args, List<Type> optTypeArguments, ResolutionContext resolutionContext, boo
 6333      Contract.Requires(tok != null);
 6334      Contract.Requires(receiver != null);
 6335      Contract.Requires(receiver.WasResolved());
 6336      Contract.Requires(member != null);
 6337      Contract.Requires(resolutionContext != null && resolutionContext.CodeContext != null);
 6338
 112956339      var rr = new MemberSelectExpr(tok, receiver, member.Name);
 112956340      rr.Member = member;
 6341
 6342      // Now, fill in rr.Type.  This requires taking into consideration the type parameters passed to the receiver's typ
 6343      // parameters used in this NameSegment/ExprDotName.
 6344      // Add to "subst" the type parameters given to the member's class/datatype
 112956345      rr.TypeApplication_AtEnclosingClass = new List<Type>();
 112956346      rr.TypeApplication_JustMember = new List<Type>();
 6347      Dictionary<TypeParameter, Type> subst;
 112956348      var rType = (receiverTypeBound ?? receiver.Type).NormalizeExpand();
 224256349      if (rType is UserDefinedType udt && udt.ResolvedClass != null) {
 111306350        subst = TypeParameter.SubstitutionMap(udt.ResolvedClass.TypeArgs, udt.TypeArgs);
 111306351        if (member.EnclosingClass == null) {
 6352          // this can happen for some special members, like real.Floor
 111306353        } else {
 111306354          rr.TypeApplication_AtEnclosingClass.AddRange(rType.AsParentType(member.EnclosingClass).TypeArgs);
 111306355        }
 112956356      } else {
 1656357        var vtd = AsValuetypeDecl(rType);
 3306358        if (vtd != null) {
 1656359          Contract.Assert(vtd.TypeArgs.Count == rType.TypeArgs.Count);
 1656360          subst = TypeParameter.SubstitutionMap(vtd.TypeArgs, rType.TypeArgs);
 1656361          rr.TypeApplication_AtEnclosingClass.AddRange(rType.TypeArgs);
 1656362        } else {
 06363          Contract.Assert(rType.TypeArgs.Count == 0);
 06364          subst = new Dictionary<TypeParameter, Type>();
 06365        }
 1656366      }
 6367
 191196368      if (member is Field) {
 78246369        var field = (Field)member;
 78246370        if (optTypeArguments != null) {
 06371          reporter.Error(MessageSource.Resolver, tok, "a field ({0}) does not take any type arguments (got {1})", field.
 06372        }
 78246373        subst = BuildTypeArgumentSubstitute(subst, receiverTypeBound ?? receiver.Type);
 78246374        rr.Type = field.Type.Subst(subst);
 112956375      } else if (member is Function) {
 06376        var fn = (Function)member;
 06377        if (fn is TwoStateFunction && !resolutionContext.IsTwoState) {
 06378          reporter.Error(MessageSource.Resolver, tok, "two-state function ('{0}') can only be called in a two-state cont
 06379        }
 06380        int suppliedTypeArguments = optTypeArguments == null ? 0 : optTypeArguments.Count;
 06381        if (optTypeArguments != null && suppliedTypeArguments != fn.TypeArgs.Count) {
 06382          reporter.Error(MessageSource.Resolver, tok, "function '{0}' expects {1} type argument{2} (got {3})",
 06383            member.Name, fn.TypeArgs.Count, Util.Plural(fn.TypeArgs.Count), suppliedTypeArguments);
 06384        }
 06385        for (int i = 0; i < fn.TypeArgs.Count; i++) {
 06386          var ta = i < suppliedTypeArguments ? optTypeArguments[i] : new InferredTypeProxy();
 06387          rr.TypeApplication_JustMember.Add(ta);
 06388          subst.Add(fn.TypeArgs[i], ta);
 06389        }
 06390        subst = BuildTypeArgumentSubstitute(subst, receiverTypeBound ?? receiver.Type);
 06391        rr.Type = SelectAppropriateArrowTypeForFunction(fn, subst, builtIns);
 34716392      } else {
 6393        // the member is a method
 34716394        var m = (Method)member;
 34716395        if (!allowMethodCall) {
 6396          // it's a method and method calls are not allowed in the given context
 06397          reporter.Error(MessageSource.Resolver, tok, "expression is not allowed to invoke a {0} ({1})", member.WhatKind
 06398        }
 34716399        int suppliedTypeArguments = optTypeArguments == null ? 0 : optTypeArguments.Count;
 34716400        if (optTypeArguments != null && suppliedTypeArguments != m.TypeArgs.Count) {
 06401          reporter.Error(MessageSource.Resolver, tok, "method '{0}' expects {1} type argument{2} (got {3})",
 06402            member.Name, m.TypeArgs.Count, Util.Plural(m.TypeArgs.Count), suppliedTypeArguments);
 06403        }
 135186404        for (int i = 0; i < m.TypeArgs.Count; i++) {
 21926405          var ta = i < suppliedTypeArguments ? optTypeArguments[i] : new InferredTypeProxy();
 21926406          rr.TypeApplication_JustMember.Add(ta);
 21926407          subst.Add(m.TypeArgs[i], ta);
 21926408        }
 34716409        subst = BuildTypeArgumentSubstitute(subst, receiverTypeBound ?? receiver.Type);
 72776410        rr.ResolvedOutparameterTypes = m.Outs.ConvertAll(f => f.Type.Subst(subst));
 34716411        rr.Type = new InferredTypeProxy();  // fill in this field, in order to make "rr" resolved
 34716412      }
 112956413      return rr;
 112956414    }
 6415
 58516416    public MethodCallInformation ResolveApplySuffix(ApplySuffix e, ResolutionContext resolutionContext, bool allowMethod
 6417      Contract.Requires(e != null);
 6418      Contract.Requires(resolutionContext != null);
 6419      Contract.Ensures(Contract.Result<MethodCallInformation>() == null || allowMethodCall);
 58516420      Expression r = null;  // upon success, the expression to which the ApplySuffix resolves
 58516421      var errorCount = reporter.Count(ErrorLevel.Error);
 117026422      if (e.Lhs is NameSegment) {
 58516423        r = ResolveNameSegment((NameSegment)e.Lhs, true, e.Bindings.ArgumentBindings, resolutionContext, allowMethodCall
 6424        // note, if r is non-null, then e.Args have been resolved and r is a resolved expression that incorporates e.Arg
 58516425      } else if (e.Lhs is ExprDotName) {
 06426        r = ResolveDotSuffix((ExprDotName)e.Lhs, true, e.Bindings.ArgumentBindings, resolutionContext, allowMethodCall);
 6427        // note, if r is non-null, then e.Args have been resolved and r is a resolved expression that incorporates e.Arg
 06428      } else {
 06429        ResolveExpression(e.Lhs, resolutionContext);
 06430      }
 58516431      if (e.Lhs.Type == null) {
 6432        // some error had been detected during the attempted resolution of e.Lhs
 06433        e.Lhs.Type = new InferredTypeProxy();
 06434      }
 58516435      Label atLabel = null;
 58516436      if (e.AtTok != null) {
 06437        atLabel = DominatingStatementLabels.Find(e.AtTok.val);
 06438        if (atLabel == null) {
 06439          reporter.Error(MessageSource.Resolver, e.AtTok, "no label '{0}' in scope at this time", e.AtTok.val);
 06440        }
 06441      }
 93226442      if (r == null) {
 34716443        var improvedType = PartiallyResolveTypeForMemberSelection(e.Lhs.tok, e.Lhs.Type, "_#apply");
 34716444        var fnType = improvedType.AsArrowType;
 69426445        if (fnType == null) {
 34716446          var lhs = e.Lhs.Resolved;
 34716447          if (lhs != null && lhs.Type is Resolver_IdentifierExpr.ResolverType_Module) {
 06448            reporter.Error(MessageSource.Resolver, e.tok, "name of module ({0}) is used as a function", ((Resolver_Ident
 34716449          } else if (lhs != null && lhs.Type is Resolver_IdentifierExpr.ResolverType_Type) {
 06450            var ri = (Resolver_IdentifierExpr)lhs;
 06451            reporter.Error(MessageSource.Resolver, e.tok, "name of {0} ({1}) is used as a function", ri.Decl.WhatKind, r
 34716452          } else {
 69426453            if (lhs is MemberSelectExpr mse && mse.Member is Method) {
 34716454              if (atLabel != null) {
 06455                Contract.Assert(mse != null); // assured by the parser
 06456                if (mse.Member is TwoStateLemma) {
 06457                  mse.AtLabel = atLabel;
 06458                } else {
 06459                  reporter.Error(MessageSource.Resolver, e.AtTok, "an @-label can only be applied to a two-state lemma")
 06460                }
 06461              }
 69426462              if (allowMethodCall) {
 34716463                Contract.Assert(!e.Bindings.WasResolved); // we expect that .Bindings has not yet been processed, so we 
 34716464                var tok = Options.Get(DafnyConsolePrinter.ShowSnippets) ? e.RangeToken.ToToken() : e.tok;
 34716465                var cRhs = new MethodCallInformation(tok, mse, e.Bindings.ArgumentBindings);
 34716466                return cRhs;
 06467              } else {
 06468                reporter.Error(MessageSource.Resolver, e.tok, "{0} call is not allowed to be used in an expression conte
 06469              }
 06470            } else if (lhs != null) {  // if e.Lhs.Resolved is null, then e.Lhs was not successfully resolved and an err
 06471              reporter.Error(MessageSource.Resolver, e.tok, "non-function expression (of type {0}) is called with parame
 06472            }
 06473          }
 6474          // resolve the arguments, even in the presence of the errors above
 06475          foreach (var binding in e.Bindings.ArgumentBindings) {
 06476            ResolveExpression(binding.Actual, resolutionContext);
 06477          }
 06478        } else {
 06479          var mse = e.Lhs is NameSegment || e.Lhs is ExprDotName ? e.Lhs.Resolved as MemberSelectExpr : null;
 06480          var callee = mse == null ? null : mse.Member as Function;
 06481          if (atLabel != null && !(callee is TwoStateFunction)) {
 06482            reporter.Error(MessageSource.Resolver, e.AtTok, "an @-label can only be applied to a two-state function");
 06483            atLabel = null;
 06484          }
 06485          if (callee != null) {
 6486            // produce a FunctionCallExpr instead of an ApplyExpr(MemberSelectExpr)
 06487            var rr = new FunctionCallExpr(e.Lhs.tok, callee.Name, mse.Obj, e.tok, e.CloseParen, e.Bindings, atLabel) {
 06488              Function = callee,
 06489              TypeApplication_AtEnclosingClass = mse.TypeApplication_AtEnclosingClass,
 06490              TypeApplication_JustFunction = mse.TypeApplication_JustMember
 06491            };
 06492            var typeMap = BuildTypeArgumentSubstitute(mse.TypeArgumentSubstitutionsAtMemberDeclaration());
 06493            ResolveActualParameters(rr.Bindings, callee.Formals, e.tok, callee, resolutionContext, typeMap, callee.IsSta
 06494            rr.Type = callee.ResultType.Subst(typeMap);
 06495            if (errorCount == reporter.Count(ErrorLevel.Error)) {
 06496              Contract.Assert(!(mse.Obj is StaticReceiverExpr) || callee.IsStatic);  // this should have been checked al
 06497              Contract.Assert(callee.Formals.Count == rr.Args.Count);  // this should have been checked already
 06498            }
 06499            r = rr;
 06500          } else {
 6501            List<Formal> formals;
 06502            if (callee != null) {
 06503              formals = callee.Formals;
 06504            } else {
 06505              formals = new List<Formal>();
 06506              for (var i = 0; i < fnType.Args.Count; i++) {
 06507                var argType = fnType.Args[i];
 06508                var formal = new ImplicitFormal(e.tok, "_#p" + i, argType, true, false);
 06509                formals.Add(formal);
 06510              }
 06511            }
 06512            ResolveActualParameters(e.Bindings, formals, e.tok, fnType, resolutionContext, new Dictionary<TypeParameter,
 06513            r = new ApplyExpr(e.Lhs.tok, e.Lhs, e.Args, e.CloseParen);
 06514            r.Type = fnType.Result;
 06515          }
 06516        }
 06517      }
 23806518      if (r == null) {
 6519        // an error has been reported above; we won't fill in .ResolvedExpression, but we still must fill in .Type
 06520        e.Type = new InferredTypeProxy();
 23806521      } else {
 23806522        e.ResolvedExpression = r;
 23806523        e.Type = r.Type;
 23806524      }
 23806525      return null;
 58516526    }
 6527
 6528    /// <summary>
 6529    /// the return value is false iff there is an error in resolving the datatype value;
 6530    /// if there is an error then an error message is emitted iff complain is true
 6531    /// </summary>
 122746532    private bool ResolveDatatypeValue(ResolutionContext resolutionContext, DatatypeValue dtv, DatatypeDecl dt, Type ty, 
 6533      Contract.Requires(resolutionContext != null);
 6534      Contract.Requires(dtv != null);
 6535      Contract.Requires(dt != null);
 6536      Contract.Requires(ty == null || (ty.AsDatatype == dt && ty.TypeArgs.Count == dt.TypeArgs.Count));
 6537
 122746538      var ok = true;
 122746539      var gt = new List<Type>(dt.TypeArgs.Count);
 122746540      var subst = new Dictionary<TypeParameter, Type>();
 874376541      for (int i = 0; i < dt.TypeArgs.Count; i++) {
 209636542        Type t = ty == null ? new InferredTypeProxy() : ty.TypeArgs[i];
 209636543        gt.Add(t);
 209636544        dtv.InferredTypeArgs.Add(t);
 209636545        subst.Add(dt.TypeArgs[i], t);
 209636546      }
 6547      // Construct a resolved type directly, as we know the declaration is dt.
 122746548      dtv.Type = new UserDefinedType(dtv.tok, dt.Name, dt, gt);
 6549
 122746550      if (!dt.ConstructorsByName.TryGetValue(dtv.MemberName, out var ctor)) {
 06551        ok = false;
 06552        if (complain) {
 06553          reporter.Error(MessageSource.Resolver, dtv.tok, "undeclared constructor {0} in datatype {1}", dtv.MemberName, 
 06554        }
 122746555      } else {
 122746556        Contract.Assert(ctor != null);  // follows from postcondition of TryGetValue
 122746557        dtv.Ctor = ctor;
 122746558      }
 245486559      if (complain && ctor != null) {
 122746560        ResolveActualParameters(dtv.Bindings, ctor.Formals, dtv.tok, ctor, resolutionContext, subst, null);
 122746561      } else {
 6562        // still resolve the expressions
 06563        foreach (var binding in dtv.Bindings.ArgumentBindings) {
 06564          ResolveExpression(binding.Actual, resolutionContext);
 06565        }
 06566        dtv.Bindings.AcceptArgumentExpressionsAsExactParameterList();
 06567      }
 6568
 122746569      return ok && ctor.Formals.Count == dtv.Arguments.Count;
 122746570    }
 6571
 06572    public void ResolveFunctionCallExpr(FunctionCallExpr e, ResolutionContext resolutionContext) {
 6573      Contract.Requires(e != null);
 6574      Contract.Requires(e.Type == null);  // should not have been type checked before
 6575
 06576      ResolveReceiver(e.Receiver, resolutionContext);
 06577      Contract.Assert(e.Receiver.Type != null);  // follows from postcondition of ResolveExpression
 6578
 06579      var member = ResolveMember(e.tok, e.Receiver.Type, e.Name, out var tentativeReceiverType);
 6580#if !NO_WORK_TO_BE_DONE
 06581      var ctype = (UserDefinedType)tentativeReceiverType;
 6582#endif
 06583      if (member == null) {
 6584        // error has already been reported by ResolveMember
 06585      } else if (member is Method) {
 06586        reporter.Error(MessageSource.Resolver, e, "member {0} in type {1} refers to a method, but only functions can be 
 06587      } else if (!(member is Function)) {
 06588        reporter.Error(MessageSource.Resolver, e, "member {0} in type {1} does not refer to a function", e.Name, cce.Non
 06589      } else {
 06590        Function function = (Function)member;
 06591        e.Function = function;
 06592        if (function is TwoStateFunction && !resolutionContext.IsTwoState) {
 06593          reporter.Error(MessageSource.Resolver, e.tok, "a two-state function can be used only in a two-state context");
 06594        }
 06595        if (e.Receiver is StaticReceiverExpr && !function.IsStatic) {
 06596          reporter.Error(MessageSource.Resolver, e, "an instance function must be selected via an object, not just a cla
 06597        }
 06598        Contract.Assert(ctype != null);  // follows from postcondition of ResolveMember
 06599        if (!function.IsStatic) {
 06600          if (!scope.AllowInstance && e.Receiver is ThisExpr) {
 6601            // The call really needs an instance, but that instance is given as 'this', which is not
 6602            // available in this context.  In most cases, occurrences of 'this' inside e.Receiver would
 6603            // have been caught in the recursive call to resolve e.Receiver, but not the specific case
 6604            // of e.Receiver being 'this' (explicitly or implicitly), for that case needs to be allowed
 6605            // in the event that a static function calls another static function (and note that we need the
 6606            // type of the receiver in order to find the method, so we could not have made this check
 6607            // earlier).
 06608            reporter.Error(MessageSource.Resolver, e.Receiver, "'this' is not allowed in a 'static' context");
 06609          } else if (e.Receiver is StaticReceiverExpr) {
 06610            reporter.Error(MessageSource.Resolver, e.Receiver, "call to instance function requires an instance");
 06611          }
 06612        }
 6613        // build the type substitution map
 06614        var typeMap = new Dictionary<TypeParameter, Type>();
 06615        for (int i = 0; i < ctype.TypeArgs.Count; i++) {
 06616          typeMap.Add(ctype.ResolvedClass.TypeArgs[i], ctype.TypeArgs[i]);
 06617        }
 06618        var typeThatEnclosesMember = ctype.AsParentType(member.EnclosingClass);
 06619        e.TypeApplication_AtEnclosingClass = new List<Type>();
 06620        for (int i = 0; i < typeThatEnclosesMember.TypeArgs.Count; i++) {
 06621          e.TypeApplication_AtEnclosingClass.Add(typeThatEnclosesMember.TypeArgs[i]);
 06622        }
 06623        e.TypeApplication_JustFunction = new List<Type>();
 06624        foreach (TypeParameter p in function.TypeArgs) {
 06625          var ty = new ParamTypeProxy(p);
 06626          typeMap.Add(p, ty);
 06627          e.TypeApplication_JustFunction.Add(ty);
 06628        }
 06629        Dictionary<TypeParameter, Type> subst = BuildTypeArgumentSubstitute(typeMap);
 6630
 6631        // type check the arguments
 06632        ResolveActualParameters(e.Bindings, function.Formals, e.tok, function, resolutionContext, subst, function.IsStat
 6633
 06634        e.Type = function.ResultType.Subst(subst).NormalizeExpand();
 06635      }
 06636    }
 6637
 06638    void ResolveReceiver(Expression expr, ResolutionContext resolutionContext) {
 6639      Contract.Requires(expr != null);
 6640      Contract.Ensures(expr.Type != null);
 6641
 06642      if (expr is ThisExpr && !expr.WasResolved()) {
 6643        // Allow 'this' here, regardless of scope.AllowInstance.  The caller is responsible for
 6644        // making sure 'this' does not really get used when it's not available.
 06645        Contract.Assume(currentClass != null);  // this is really a precondition, in this case
 06646        expr.Type = GetThisType(expr.tok, currentClass);
 06647      } else {
 06648        ResolveExpression(expr, resolutionContext);
 06649      }
 06650    }
 6651
 135016652    void ResolveSeqSelectExpr(SeqSelectExpr e, ResolutionContext resolutionContext) {
 6653      Contract.Requires(e != null);
 135016654      if (e.Type != null) {
 6655        // already resolved
 06656        return;
 6657      }
 6658
 135016659      ResolveExpression(e.Seq, resolutionContext);
 135016660      Contract.Assert(e.Seq.Type != null);  // follows from postcondition of ResolveExpression
 6661
 262676662      if (e.SelectOne) {
 127666663        AddXConstraint(e.tok, "Indexable", e.Seq.Type, "element selection requires a sequence, array, multiset, or map (
 127666664        ResolveExpression(e.E0, resolutionContext);
 127666665        AddXConstraint(e.E0.tok, "ContainerIndex", e.Seq.Type, e.E0.Type, "incorrect type for selection into {0} (got {1
 127666666        Contract.Assert(e.E1 == null);
 127666667        e.Type = new InferredTypeProxy() { KeepConstraints = true };
 127666668        AddXConstraint(e.tok, "ContainerResult",
 127666669          e.Seq.Type, e.Type,
 127666670          new SeqSelectOneErrorMsg(e.tok, e.Seq.Type, e.Type));
 135016671      } else {
 7356672        AddXConstraint(e.tok, "MultiIndexable", e.Seq.Type, "multi-selection of elements requires a sequence or array (g
 14706673        if (e.E0 != null) {
 7356674          ResolveExpression(e.E0, resolutionContext);
 7356675          AddXConstraint(e.E0.tok, "ContainerIndex", e.Seq.Type, e.E0.Type, "incorrect type for selection into {0} (got 
 7356676          ConstrainSubtypeRelation(NewIntegerBasedProxy(e.tok), e.E0.Type, e.E0, "wrong number of indices for multi-sele
 7356677        }
 14706678        if (e.E1 != null) {
 7356679          ResolveExpression(e.E1, resolutionContext);
 7356680          AddXConstraint(e.E1.tok, "ContainerIndex", e.Seq.Type, e.E1.Type, "incorrect type for selection into {0} (got 
 7356681          ConstrainSubtypeRelation(NewIntegerBasedProxy(e.tok), e.E1.Type, e.E1, "wrong number of indices for multi-sele
 7356682        }
 7356683        var resultType = new InferredTypeProxy() { KeepConstraints = true };
 7356684        e.Type = new SeqType(resultType);
 7356685        AddXConstraint(e.tok, "ContainerResult", e.Seq.Type, resultType, "multi-selection has type {0} which is incompat
 7356686      }
 135016687    }
 6688
 6689  }
 6690
 6691  public class MethodCallInformation {
 6692    public readonly IToken Tok;
 6693    public readonly MemberSelectExpr Callee;
 6694    public readonly List<ActualBinding> ActualParameters;
 6695
 6696    [ContractInvariantMethod]
 6697    void ObjectInvariant() {
 6698      Contract.Invariant(Tok != null);
 6699      Contract.Invariant(Callee != null);
 6700      Contract.Invariant(Callee.Member is Method);
 6701      Contract.Invariant(ActualParameters != null);
 6702    }
 6703
 6704    public MethodCallInformation(IToken tok, MemberSelectExpr callee, List<ActualBinding> actualParameters) {
 6705      Contract.Requires(tok != null);
 6706      Contract.Requires(callee != null);
 6707      Contract.Requires(callee.Member is Method);
 6708      Contract.Requires(actualParameters != null);
 6709      this.Tok = tok;
 6710      this.Callee = callee;
 6711      this.ActualParameters = actualParameters;
 6712    }
 6713  }
 6714}

/home/ubuntu/dafny-verifier/src/main/dafny_compiler/dafny/Source/DafnyCore/Resolver/Resolver.cs

#LineLine coverage
 1//-----------------------------------------------------------------------------
 2//
 3// Copyright (C) Microsoft Corporation.  All Rights Reserved.
 4// Copyright by the contributors to the Dafny Project
 5// SPDX-License-Identifier: MIT
 6//
 7//-----------------------------------------------------------------------------
 8using System;
 9using System.Collections.Generic;
 10using System.Linq;
 11using System.Numerics;
 12using System.Diagnostics.Contracts;
 13using System.IO;
 14using System.Reflection;
 15using JetBrains.Annotations;
 16using Microsoft.BaseTypes;
 17using Microsoft.Boogie;
 18using Microsoft.CodeAnalysis.CSharp.Syntax;
 19using Microsoft.Dafny.Plugins;
 20using static Microsoft.Dafny.ErrorRegistry;
 21
 22namespace Microsoft.Dafny {
 23  interface ICanResolve {
 24    void Resolve(Resolver resolver, ResolutionContext context);
 25  }
 26
 27  public enum FrameExpressionUse { Reads, Modifies, Unchanged }
 28
 29  public partial class Resolver {
 214920930    public DafnyOptions Options { get; }
 31    public readonly BuiltIns builtIns;
 32
 33    public ErrorReporter reporter;
 11234    ModuleSignature moduleInfo = null;
 35
 17399236    public ErrorReporter Reporter => reporter;
 2229037    public List<TypeConstraint.ErrorMsg> TypeConstraintErrorsToBeReported { get; } = new();
 38
 039    private bool RevealedInScope(Declaration d) {
 40      Contract.Requires(d != null);
 41      Contract.Requires(moduleInfo != null);
 42      Contract.Requires(moduleInfo.VisibilityScope != null);
 43
 044      return useCompileSignatures || d.IsRevealedInScope(moduleInfo.VisibilityScope);
 045    }
 46
 1384347    private bool VisibleInScope(Declaration d) {
 48      Contract.Requires(d != null);
 49      Contract.Requires(moduleInfo != null);
 50      Contract.Requires(moduleInfo.VisibilityScope != null);
 51
 1384352      return useCompileSignatures || d.IsVisibleInScope(moduleInfo.VisibilityScope);
 1384353    }
 54
 11255    public FreshIdGenerator defaultTempVarIdGenerator = new FreshIdGenerator();
 56
 057    public string FreshTempVarName(string prefix, ICodeContext context) {
 058      var gen = context is Declaration decl ? decl.IdGenerator : defaultTempVarIdGenerator;
 059      var freshTempVarName = gen.FreshId(prefix);
 060      return freshTempVarName;
 061    }
 62
 63    interface IAmbiguousThing<Thing> {
 64      /// <summary>
 65      /// Returns a plural number of non-null Thing's
 66      /// </summary>
 67      ISet<Thing> Pool { get; }
 68    }
 69
 70    class AmbiguousThingHelper<Thing> where Thing : class {
 071      public static Thing Create(ModuleDefinition m, Thing a, Thing b, IEqualityComparer<Thing> eq, out ISet<Thing> s) {
 72        Contract.Requires(a != null);
 73        Contract.Requires(b != null);
 74        Contract.Requires(eq != null);
 75        Contract.Ensures(Contract.Result<Thing>() != null ||
 76                         Contract.ValueAtReturn(out s) != null || 2 <= Contract.ValueAtReturn(out s).Count);
 077        s = null;
 078        if (eq.Equals(a, b)) {
 079          return a;
 80        }
 81
 082        ISet<Thing> sa = a is IAmbiguousThing<Thing> ? ((IAmbiguousThing<Thing>)a).Pool : new HashSet<Thing>() { a };
 083        ISet<Thing> sb = b is IAmbiguousThing<Thing> ? ((IAmbiguousThing<Thing>)b).Pool : new HashSet<Thing>() { b };
 084        var union = new HashSet<Thing>(sa.Union(sb, eq));
 085        if (sa.Count == union.Count) {
 86          // sb is a subset of sa
 087          return a;
 088        } else if (sb.Count == union.Count) {
 89          // sa is a subset of sb
 090          return b;
 091        } else {
 092          s = union;
 093          Contract.Assert(2 <= s.Count);
 094          return null;
 95        }
 096      }
 97
 098      public static string Name(ISet<Thing> s, Func<Thing, string> name) {
 99        Contract.Requires(s != null);
 100        Contract.Requires(s.Count != 0);
 0101        string nm = null;
 0102        foreach (var thing in s) {
 0103          string n = name(thing);
 0104          if (nm == null) {
 0105            nm = n;
 0106          } else {
 0107            nm += "/" + n;
 0108          }
 0109        }
 110
 0111        return nm;
 0112      }
 113
 0114      public static string ModuleNames(IAmbiguousThing<Thing> amb, Func<Thing, string> moduleName) {
 115        Contract.Requires(amb != null);
 116        Contract.Ensures(Contract.Result<string>() != null);
 0117        string nm = null;
 0118        foreach (var d in amb.Pool) {
 0119          if (nm == null) {
 0120            nm = moduleName(d);
 0121          } else {
 0122            nm += ", " + moduleName(d);
 0123          }
 0124        }
 125
 0126        return nm;
 0127      }
 128    }
 129
 130    public class AmbiguousTopLevelDecl : TopLevelDecl, IAmbiguousThing<TopLevelDecl> // only used with "classes"
 131    {
 0132      public static TopLevelDecl Create(ModuleDefinition m, TopLevelDecl a, TopLevelDecl b) {
 0133        var t = AmbiguousThingHelper<TopLevelDecl>.Create(m, a, b, new Eq(), out var s);
 0134        return t ?? new AmbiguousTopLevelDecl(m, AmbiguousThingHelper<TopLevelDecl>.Name(s, tld => tld.Name), s);
 0135      }
 136
 137      class Eq : IEqualityComparer<TopLevelDecl> {
 0138        public bool Equals(TopLevelDecl d0, TopLevelDecl d1) {
 139          // We'd like to resolve any AliasModuleDecl to whatever module they refer to.
 140          // It seems that the only way to do that is to look at alias.Signature.ModuleDef,
 141          // but that is a ModuleDefinition, which is not a TopLevelDecl.  Therefore, we
 142          // convert to a ModuleDefinition anything that might refer to something that an
 143          // AliasModuleDecl can refer to; this is AliasModuleDecl and LiteralModuleDecl.
 0144          object a = d0 is ModuleDecl ? ((ModuleDecl)d0).Dereference() : d0;
 0145          object b = d1 is ModuleDecl ? ((ModuleDecl)d1).Dereference() : d1;
 0146          return a == b;
 0147        }
 148
 0149        public int GetHashCode(TopLevelDecl d) {
 0150          object a = d is ModuleDecl ? ((ModuleDecl)d).Dereference() : d;
 0151          return a.GetHashCode();
 0152        }
 153      }
 154
 155      public override string WhatKind {
 0156        get { return Pool.First().WhatKind; }
 157      }
 158
 0159      readonly ISet<TopLevelDecl> Pool = new HashSet<TopLevelDecl>();
 160
 161      ISet<TopLevelDecl> IAmbiguousThing<TopLevelDecl>.Pool {
 0162        get { return Pool; }
 163      }
 164
 165      private AmbiguousTopLevelDecl(ModuleDefinition m, string name, ISet<TopLevelDecl> pool)
 0166        : base(pool.First().RangeToken, new Name(pool.First().RangeToken, name), m, new List<TypeParameter>(), null, fal
 167        Contract.Requires(name != null);
 168        Contract.Requires(pool != null && 2 <= pool.Count);
 0169        Pool = pool;
 0170      }
 171
 0172      public string ModuleNames() {
 0173        return AmbiguousThingHelper<TopLevelDecl>.ModuleNames(this, d => d.EnclosingModuleDefinition.Name);
 0174      }
 175    }
 176
 177    class AmbiguousMemberDecl : MemberDecl, IAmbiguousThing<MemberDecl> // only used with "classes"
 178    {
 0179      public static MemberDecl Create(ModuleDefinition m, MemberDecl a, MemberDecl b) {
 180        ISet<MemberDecl> s;
 0181        var t = AmbiguousThingHelper<MemberDecl>.Create(m, a, b, new Eq(), out s);
 0182        return t ?? new AmbiguousMemberDecl(m, AmbiguousThingHelper<MemberDecl>.Name(s, member => member.Name), s);
 0183      }
 184
 185      class Eq : IEqualityComparer<MemberDecl> {
 0186        public bool Equals(MemberDecl d0, MemberDecl d1) {
 0187          return d0 == d1;
 0188        }
 189
 0190        public int GetHashCode(MemberDecl d) {
 0191          return d.GetHashCode();
 0192        }
 193      }
 194
 195      public override string WhatKind {
 0196        get { return Pool.First().WhatKind; }
 197      }
 198
 0199      readonly ISet<MemberDecl> Pool = new HashSet<MemberDecl>();
 200
 201      ISet<MemberDecl> IAmbiguousThing<MemberDecl>.Pool {
 0202        get { return Pool; }
 203      }
 204
 205      private AmbiguousMemberDecl(ModuleDefinition m, string name, ISet<MemberDecl> pool)
 0206        : base(pool.First().RangeToken, new Name(pool.First().RangeToken, name), true, pool.First().IsGhost, null, false
 207        Contract.Requires(name != null);
 208        Contract.Requires(pool != null && 2 <= pool.Count);
 0209        Pool = pool;
 0210      }
 211
 0212      public string ModuleNames() {
 0213        return AmbiguousThingHelper<MemberDecl>.ModuleNames(this, d => d.EnclosingClass.EnclosingModuleDefinition.Name);
 0214      }
 215    }
 216
 112217    readonly HashSet<RevealableTypeDecl> revealableTypes = new HashSet<RevealableTypeDecl>();
 218    //types that have been seen by the resolver - used for constraining type inference during exports
 219
 112220    public readonly Dictionary<TopLevelDeclWithMembers, Dictionary<string, MemberDecl>> classMembers =
 112221      new Dictionary<TopLevelDeclWithMembers, Dictionary<string, MemberDecl>>();
 222
 223    enum ValuetypeVariety {
 224      Bool = 0,
 225      Int,
 226      Real,
 227      BigOrdinal,
 228      Bitvector,
 229      Map,
 230      IMap,
 231      None
 232    } // note, these are ordered, so they can be used as indices into valuetypeDecls
 233
 234    internal readonly ValuetypeDecl[] valuetypeDecls;
 235    private Dictionary<TypeParameter, Type> SelfTypeSubstitution;
 112236    readonly Graph<ModuleDecl> dependencies = new Graph<ModuleDecl>();
 112237    private ModuleSignature systemNameInfo = null;
 112238    private bool useCompileSignatures = false;
 239
 240    private List<IRewriter> rewriters;
 241    private RefinementTransformer refinementTransformer;
 242
 0243    public Resolver(DafnyOptions options) {
 0244      Options = options;
 0245    }
 246
 224247    public Resolver(Program prog) {
 112248      Options = prog.Options;
 249
 112250      allTypeParameters = new Scope<TypeParameter>(Options);
 112251      scope = new Scope<IVariable>(Options);
 112252      enclosingStatementLabels = new Scope<Statement>(Options);
 112253      DominatingStatementLabels = new Scope<Label>(Options);
 254
 255      Contract.Requires(prog != null);
 256
 112257      builtIns = prog.BuiltIns;
 112258      reporter = prog.Reporter;
 259
 260      // Map#Items relies on the two destructors for 2-tuples
 112261      builtIns.TupleType(Token.NoToken, 2, true);
 262      // Several methods and fields rely on 1-argument arrow types
 112263      builtIns.CreateArrowTypeDecl(1);
 264
 112265      valuetypeDecls = new ValuetypeDecl[] {
 7989266        new ValuetypeDecl("bool", builtIns.SystemModule, t => t.IsBoolType, typeArgs => Type.Bool),
 7989267        new ValuetypeDecl("int", builtIns.SystemModule, t => t.IsNumericBased(Type.NumericPersuasion.Int), typeArgs => T
 7989268        new ValuetypeDecl("real", builtIns.SystemModule, t => t.IsNumericBased(Type.NumericPersuasion.Real), typeArgs =>
 7699269        new ValuetypeDecl("ORDINAL", builtIns.SystemModule, t => t.IsBigOrdinalType, typeArgs => Type.BigOrdinal),
 7699270        new ValuetypeDecl("_bv", builtIns.SystemModule, t => t.IsBitVectorType, null), // "_bv" represents a family of c
 112271        new ValuetypeDecl("map", builtIns.SystemModule,
 112272          new List<TypeParameter.TPVarianceSyntax>() { TypeParameter.TPVarianceSyntax.Covariant_Strict , TypeParameter.T
 7699273          t => t.IsMapType, typeArgs => new MapType(true, typeArgs[0], typeArgs[1])),
 112274        new ValuetypeDecl("imap", builtIns.SystemModule,
 112275          new List<TypeParameter.TPVarianceSyntax>() { TypeParameter.TPVarianceSyntax.Covariant_Permissive , TypeParamet
 7659276          t => t.IsIMapType, typeArgs => new MapType(false, typeArgs[0], typeArgs[1]))
 112277      };
 112278      builtIns.SystemModule.TopLevelDecls.AddRange(valuetypeDecls);
 279      // Resolution error handling relies on being able to get to the 0-tuple declaration
 112280      builtIns.TupleType(Token.NoToken, 0, true);
 281
 282      // Populate the members of the basic types
 283
 1232284      void AddMember(MemberDecl member, ValuetypeVariety valuetypeVariety) {
 1232285        var enclosingType = valuetypeDecls[(int)valuetypeVariety];
 1232286        member.EnclosingClass = enclosingType;
 1232287        member.AddVisibilityScope(prog.BuiltIns.SystemModule.VisibilityScope, false);
 1232288        enclosingType.Members.Add(member.Name, member);
 1232289      }
 290
 112291      var floor = new SpecialField(RangeToken.NoToken, "Floor", SpecialField.ID.Floor, null, false, false, false, Type.I
 112292      AddMember(floor, ValuetypeVariety.Real);
 293
 112294      var isLimit = new SpecialField(RangeToken.NoToken, "IsLimit", SpecialField.ID.IsLimit, null, false, false, false, 
 112295      AddMember(isLimit, ValuetypeVariety.BigOrdinal);
 296
 112297      var isSucc = new SpecialField(RangeToken.NoToken, "IsSucc", SpecialField.ID.IsSucc, null, false, false, false, Typ
 112298      AddMember(isSucc, ValuetypeVariety.BigOrdinal);
 299
 112300      var limitOffset = new SpecialField(RangeToken.NoToken, "Offset", SpecialField.ID.Offset, null, false, false, false
 112301      AddMember(limitOffset, ValuetypeVariety.BigOrdinal);
 112302      builtIns.ORDINAL_Offset = limitOffset;
 303
 112304      var isNat = new SpecialField(RangeToken.NoToken, "IsNat", SpecialField.ID.IsNat, null, false, false, false, Type.B
 112305      AddMember(isNat, ValuetypeVariety.BigOrdinal);
 306
 307      // Add "Keys", "Values", and "Items" to map, imap
 1008308      foreach (var typeVariety in new[] { ValuetypeVariety.Map, ValuetypeVariety.IMap }) {
 224309        var vtd = valuetypeDecls[(int)typeVariety];
 224310        var isFinite = typeVariety == ValuetypeVariety.Map;
 311
 224312        var r = new SetType(isFinite, new UserDefinedType(vtd.TypeArgs[0]));
 224313        var keys = new SpecialField(RangeToken.NoToken, "Keys", SpecialField.ID.Keys, null, false, false, false, r, null
 314
 224315        r = new SetType(isFinite, new UserDefinedType(vtd.TypeArgs[1]));
 224316        var values = new SpecialField(RangeToken.NoToken, "Values", SpecialField.ID.Values, null, false, false, false, r
 317
 672318        var gt = vtd.TypeArgs.ConvertAll(tp => (Type)new UserDefinedType(tp));
 224319        var dt = builtIns.TupleType(Token.NoToken, 2, true);
 224320        var tupleType = new UserDefinedType(Token.NoToken, dt.Name, dt, gt);
 224321        r = new SetType(isFinite, tupleType);
 224322        var items = new SpecialField(RangeToken.NoToken, "Items", SpecialField.ID.Items, null, false, false, false, r, n
 323
 2688324        foreach (var memb in new[] { keys, values, items }) {
 672325          AddMember(memb, typeVariety);
 672326        }
 224327      }
 328
 329      // The result type of the following bitvector methods is the type of the bitvector itself. However, we're represen
 330      // a family of types rolled up in one ValuetypeDecl. Therefore, we use the special SelfType as the result type.
 112331      AddRotateMember(valuetypeDecls[(int)ValuetypeVariety.Bitvector], "RotateLeft", new SelfType());
 112332      AddRotateMember(valuetypeDecls[(int)ValuetypeVariety.Bitvector], "RotateRight", new SelfType());
 112333    }
 334
 224335    public void AddRotateMember(ValuetypeDecl enclosingType, string name, Type resultType) {
 224336      var formals = new List<Formal> { new Formal(Token.NoToken, "w", Type.Nat(), true, false, null, false) };
 224337      var rotateMember = new SpecialFunction(RangeToken.NoToken, name, builtIns.SystemModule, false, false,
 224338        new List<TypeParameter>(), formals, resultType,
 224339        new List<AttributedExpression>(), new List<FrameExpression>(), new List<AttributedExpression>(),
 224340        new Specification<Expression>(new List<Expression>(), null), null, null, null);
 224341      rotateMember.EnclosingClass = enclosingType;
 224342      rotateMember.AddVisibilityScope(builtIns.SystemModule.VisibilityScope, false);
 224343      enclosingType.Members.Add(name, rotateMember);
 224344    }
 345
 346    [ContractInvariantMethod]
 0347    void ObjectInvariant() {
 348      Contract.Invariant(builtIns != null);
 349      Contract.Invariant(cce.NonNullElements(dependencies.GetVertices()));
 350      Contract.Invariant(cce.NonNullDictionaryAndValues(classMembers) && Contract.ForAll(classMembers.Values, v => cce.N
 0351    }
 352
 165353    public ValuetypeDecl AsValuetypeDecl(Type t) {
 354      Contract.Requires(t != null);
 1995355      foreach (var vtd in valuetypeDecls) {
 720356        if (vtd.IsThisType(t)) {
 165357          return vtd;
 358        }
 390359      }
 0360      return null;
 165361    }
 362
 363    /// <summary>
 364    /// Check that now two modules that are being compiled have the same CompileName.
 365    ///
 366    /// This could happen if they are given the same name using the 'extern' declaration modifier.
 367    /// </summary>
 368    /// <param name="prog">The Dafny program being compiled.</param>
 102369    void CheckDupModuleNames(Program prog) {
 370      // Check that none of the modules have the same CompileName.
 102371      Dictionary<string, ModuleDefinition> compileNameMap = new Dictionary<string, ModuleDefinition>();
 918372      foreach (ModuleDefinition m in prog.CompileModules) {
 204373        var compileIt = true;
 204374        Attributes.ContainsBool(m.Attributes, "compile", ref compileIt);
 204375        if (m.IsAbstract || !compileIt) {
 376          // the purpose of an abstract module is to skip compilation
 0377          continue;
 378        }
 204379        string compileName = m.GetCompileName(Options);
 380        ModuleDefinition priorModDef;
 204381        if (compileNameMap.TryGetValue(compileName, out priorModDef)) {
 0382          reporter.Error(MessageSource.Resolver, m.tok,
 0383            "modules '{0}' and '{1}' both have CompileName '{2}'",
 0384            priorModDef.tok.val, m.tok.val, compileName);
 204385        } else {
 204386          compileNameMap.Add(compileName, m);
 204387        }
 204388      }
 102389    }
 390
 112391    public void ResolveProgram(Program prog) {
 392      Contract.Requires(prog != null);
 112393      Type.ResetScopes();
 394
 112395      Type.EnableScopes();
 396      // For the formatter, we ensure we take snapshots of the PrefixNamedModules
 397      // and topleveldecls
 112398      prog.DefaultModuleDef.PreResolveSnapshotForFormatter();
 112399      var origErrorCount = reporter.ErrorCount; //TODO: This is used further below, but not in the >0 comparisons in the
 112400      var bindings = new ModuleBindings(null);
 112401      var b = BindModuleNames(prog.DefaultModuleDef, bindings);
 112402      bindings.BindName(prog.DefaultModule.Name, prog.DefaultModule, b);
 112403      if (reporter.ErrorCount > 0) {
 0404        return;
 405      } // if there were errors, then the implict ModuleBindings data structure invariant
 406
 407      // is violated, so Processing dependencies will not succeed.
 112408      ProcessDependencies(prog.DefaultModule, b, dependencies);
 409      // check for cycles in the import graph
 336410      foreach (var cycle in dependencies.AllCycles()) {
 0411        ReportCycleError(cycle, m => m.tok,
 0412          m => (m is AliasModuleDecl ? "import " : "module ") + m.Name,
 0413          "module definition contains a cycle (note: parent modules implicitly depend on submodules)");
 0414      }
 415
 112416      if (reporter.ErrorCount > 0) {
 0417        return;
 418      } // give up on trying to resolve anything else
 419
 420      // fill in module heights
 112421      List<ModuleDecl> sortedDecls = dependencies.TopologicallySortedComponents();
 112422      int h = 0;
 672423      foreach (ModuleDecl md in sortedDecls) {
 112424        md.Height = h;
 224425        if (md is LiteralModuleDecl) {
 112426          var mdef = ((LiteralModuleDecl)md).ModuleDef;
 112427          mdef.Height = h;
 112428          prog.ModuleSigs.Add(mdef, null);
 112429        }
 112430        h++;
 112431      }
 432
 112433      rewriters = new List<IRewriter>();
 434
 112435      if (Options.AuditProgram) {
 0436        rewriters.Add(new Auditor.Auditor(reporter));
 0437      }
 438
 112439      refinementTransformer = new RefinementTransformer(prog);
 112440      rewriters.Add(refinementTransformer);
 224441      if (!Options.VerifyAllModules) {
 112442        rewriters.Add(new IncludedLemmaBodyRemover(prog, reporter));
 112443      }
 112444      rewriters.Add(new AutoContractsRewriter(reporter, builtIns));
 112445      rewriters.Add(new OpaqueMemberRewriter(this.reporter));
 112446      rewriters.Add(new AutoReqFunctionRewriter(this.reporter, this.builtIns));
 112447      rewriters.Add(new TimeLimitRewriter(reporter));
 112448      rewriters.Add(new ForallStmtRewriter(reporter));
 112449      rewriters.Add(new ProvideRevealAllRewriter(this.reporter));
 112450      rewriters.Add(new MatchFlattener(this.reporter, defaultTempVarIdGenerator));
 451
 224452      if (Options.AutoTriggers) {
 112453        rewriters.Add(new QuantifierSplittingRewriter(reporter));
 112454        rewriters.Add(new TriggerGeneratingRewriter(reporter));
 112455      }
 456
 112457      if (Options.TestContracts != DafnyOptions.ContractTestingMode.None) {
 0458        rewriters.Add(new ExpectContracts(reporter));
 0459      }
 460
 112461      if (Options.RunAllTests) {
 0462        rewriters.Add(new RunAllTestsMainMethod(reporter));
 0463      }
 464
 112465      rewriters.Add(new InductionRewriter(reporter));
 112466      rewriters.Add(new PrintEffectEnforcement(reporter));
 112467      rewriters.Add(new BitvectorOptimization(reporter));
 468
 112469      if (Options.DisallowConstructorCaseWithoutParentheses) {
 0470        rewriters.Add(new ConstructorWarning(reporter));
 0471      }
 112472      rewriters.Add(new LocalLinter(reporter));
 112473      rewriters.Add(new PrecedenceLinter(reporter));
 474
 1008475      foreach (var plugin in Options.Plugins) {
 224476        rewriters.AddRange(plugin.GetRewriters(reporter));
 224477      }
 478
 112479      systemNameInfo = RegisterTopLevelDecls(prog.BuiltIns.SystemModule, false);
 112480      prog.CompileModules.Add(prog.BuiltIns.SystemModule);
 112481      RevealAllInScope(prog.BuiltIns.SystemModule.TopLevelDecls, systemNameInfo.VisibilityScope);
 112482      ResolveValuetypeDecls();
 483      // The SystemModule is constructed with all its members already being resolved. Except for
 484      // the non-null type corresponding to class types.  They are resolved here:
 112485      var systemModuleClassesWithNonNullTypes =
 2280486        prog.BuiltIns.SystemModule.TopLevelDecls.Where(d => (d as ClassDecl)?.NonNullTypeDecl != null).ToList();
 1008487      foreach (var cl in systemModuleClassesWithNonNullTypes) {
 224488        var d = ((ClassDecl)cl).NonNullTypeDecl;
 224489        allTypeParameters.PushMarker();
 224490        ResolveTypeParameters(d.TypeArgs, true, d);
 224491        ResolveType(d.tok, d.Rhs, d, ResolveTypeOptionEnum.AllowPrefix, d.TypeArgs);
 224492        allTypeParameters.PopMarker();
 224493      }
 112494      ResolveTopLevelDecls_Core(ModuleDefinition.AllDeclarationsAndNonNullTypeDecls(systemModuleClassesWithNonNullTypes)
 112495        new Graph<IndDatatypeDecl>(), new Graph<CoDatatypeDecl>(), prog.BuiltIns.SystemModule.Name);
 496
 5712497      foreach (var rewriter in rewriters) {
 1792498        rewriter.PreResolve(prog);
 1792499      }
 500
 112501      var compilationModuleClones = new Dictionary<ModuleDefinition, ModuleDefinition>();
 672502      foreach (var decl in sortedDecls) {
 224503        if (decl is LiteralModuleDecl) {
 504          // The declaration is a literal module, so it has members and such that we need
 505          // to resolve. First we do refinement transformation. Then we construct the signature
 506          // of the module. This is the public, externally visible signature. Then we add in
 507          // everything that the system defines, as well as any "import" (i.e. "opened" modules)
 508          // directives (currently not supported, but this is where we would do it.) This signature,
 509          // which is only used while resolving the members of the module is stored in the (basically)
 510          // global variable moduleInfo. Then the signatures of the module members are resolved, followed
 511          // by the bodies.
 112512          var literalDecl = (LiteralModuleDecl)decl;
 112513          var m = literalDecl.ModuleDef;
 514
 112515          var errorCount = reporter.ErrorCount;
 112516          if (m.RefinementQId != null) {
 0517            ModuleDecl md = ResolveModuleQualifiedId(m.RefinementQId.Root, m.RefinementQId, reporter);
 0518            m.RefinementQId.Set(md); // If module is not found, md is null and an error message has been emitted
 0519          }
 520
 5712521          foreach (var rewriter in rewriters) {
 1792522            rewriter.PreResolve(m);
 1792523          }
 524
 112525          literalDecl.Signature = RegisterTopLevelDecls(m, true);
 112526          literalDecl.Signature.Refines = refinementTransformer.RefinedSig;
 527
 112528          var sig = literalDecl.Signature;
 529          // set up environment
 112530          var preResolveErrorCount = reporter.ErrorCount;
 531
 112532          ResolveModuleExport(literalDecl, sig);
 112533          var good = ResolveModuleDefinition(m, sig);
 534
 214535          if (good && reporter.ErrorCount == preResolveErrorCount) {
 536            // Check that the module export gives a self-contained view of the module.
 102537            CheckModuleExportConsistency(m);
 102538          }
 539
 112540          var tempVis = new VisibilityScope();
 112541          tempVis.Augment(sig.VisibilityScope);
 112542          tempVis.Augment(systemNameInfo.VisibilityScope);
 112543          Type.PushScope(tempVis);
 544
 112545          prog.ModuleSigs[m] = sig;
 546
 5252547          foreach (var rewriter in rewriters) {
 1652548            if (!good || reporter.ErrorCount != preResolveErrorCount) {
 10549              break;
 550            }
 1632551            rewriter.PostResolveIntermediate(m);
 1632552          }
 214553          if (good && reporter.ErrorCount == errorCount) {
 102554            m.SuccessfullyResolved = true;
 102555          }
 112556          Type.PopScope(tempVis);
 557
 214558          if (reporter.ErrorCount == errorCount && !m.IsAbstract) {
 559            // compilation should only proceed if everything is good, including the signature (which preResolveErrorCoun
 102560            CompilationCloner cloner = new CompilationCloner(compilationModuleClones);
 102561            var nw = cloner.CloneModuleDefinition(m, new Name(m.NameNode.RangeToken, m.GetCompileName(Options) + "_Compi
 102562            compilationModuleClones.Add(m, nw);
 102563            var oldErrorsOnly = reporter.ErrorsOnly;
 102564            reporter.ErrorsOnly = true; // turn off warning reporting for the clone
 565            // Next, compute the compile signature
 102566            Contract.Assert(!useCompileSignatures);
 102567            useCompileSignatures = true; // set Resolver-global flag to indicate that Signatures should be followed to t
 102568            Type.DisableScopes();
 102569            var compileSig = RegisterTopLevelDecls(nw, true);
 102570            compileSig.Refines = refinementTransformer.RefinedSig;
 102571            sig.CompileSignature = compileSig;
 306572            foreach (var exportDecl in sig.ExportSets.Values) {
 0573              exportDecl.Signature.CompileSignature = cloner.CloneModuleSignature(exportDecl.Signature, compileSig);
 0574            }
 575            // Now we're ready to resolve the cloned module definition, using the compile signature
 576
 102577            ResolveModuleDefinition(nw, compileSig);
 578
 5202579            foreach (var rewriter in rewriters) {
 1632580              rewriter.PostCompileCloneAndResolve(nw);
 1632581            }
 582
 102583            prog.CompileModules.Add(nw);
 102584            useCompileSignatures = false; // reset the flag
 102585            Type.EnableScopes();
 102586            reporter.ErrorsOnly = oldErrorsOnly;
 102587          }
 112588        } else if (decl is AliasModuleDecl alias) {
 589          // resolve the path
 590          ModuleSignature p;
 0591          if (ResolveExport(alias, alias.EnclosingModuleDefinition, alias.TargetQId, alias.Exports, out p, reporter)) {
 0592            if (alias.Signature == null) {
 0593              alias.Signature = p;
 0594            }
 0595          } else {
 0596            alias.Signature = new ModuleSignature(); // there was an error, give it a valid but empty signature
 0597          }
 0598        } else if (decl is AbstractModuleDecl abs) {
 599          ModuleSignature p;
 0600          if (ResolveExport(abs, abs.EnclosingModuleDefinition, abs.QId, abs.Exports, out p, reporter)) {
 0601            abs.OriginalSignature = p;
 0602            abs.Signature = MakeAbstractSignature(p, abs.FullSanitizedName, abs.Height, prog.ModuleSigs, compilationModu
 0603          } else {
 0604            abs.Signature = new ModuleSignature(); // there was an error, give it a valid but empty signature
 0605          }
 0606        } else if (decl is ModuleExportDecl) {
 0607          ((ModuleExportDecl)decl).SetupDefaultSignature();
 608
 0609          Contract.Assert(decl.Signature != null);
 0610          Contract.Assert(decl.Signature.VisibilityScope != null);
 611
 0612        } else {
 0613          Contract.Assert(false); // Unknown kind of ModuleDecl
 0614        }
 615
 112616        Contract.Assert(decl.Signature != null);
 112617      }
 618
 122619      if (reporter.ErrorCount != origErrorCount) {
 620        // do nothing else
 10621        return;
 622      }
 623
 624      // compute IsRecursive bit for mutually recursive functions and methods
 612625      foreach (var module in prog.Modules()) {
 3132626        foreach (var clbl in ModuleDefinition.AllCallables(module.TopLevelDecls)) {
 942627          if (clbl is Function) {
 0628            var fn = (Function)clbl;
 0629            if (!fn.IsRecursive) { // note, self-recursion has already been determined
 0630              int n = module.CallGraph.GetSCCSize(fn);
 0631              if (2 <= n) {
 632                // the function is mutually recursive (note, the SCC does not determine self recursion)
 0633                fn.IsRecursive = true;
 0634              }
 0635            }
 0636            if (fn.IsRecursive && fn is ExtremePredicate) {
 637              // this means the corresponding prefix predicate is also recursive
 0638              var prefixPred = ((ExtremePredicate)fn).PrefixPredicate;
 0639              if (prefixPred != null) {
 0640                prefixPred.IsRecursive = true;
 0641              }
 0642            }
 942643          } else {
 942644            var m = (Method)clbl;
 1884645            if (!m.IsRecursive) {
 646              // note, self-recursion has already been determined
 942647              int n = module.CallGraph.GetSCCSize(m);
 942648              if (2 <= n) {
 649                // the function is mutually recursive (note, the SCC does not determine self recursion)
 0650              }
 942651            }
 942652          }
 942653        }
 654
 5202655        foreach (var rewriter in rewriters) {
 1632656          rewriter.PostCyclicityResolve(module);
 1632657        }
 102658      }
 659
 660      // fill in default decreases clauses:  for functions and methods, and for loops
 102661      new InferDecreasesClause(this).FillInDefaultDecreasesClauses(prog);
 612662      foreach (var module in prog.Modules()) {
 3132663        foreach (var clbl in ModuleDefinition.AllItersAndCallables(module.TopLevelDecls)) {
 942664          Statement body = null;
 1884665          if (clbl is Method) {
 942666            body = ((Method)clbl).Body;
 942667          } else if (clbl is IteratorDecl) {
 0668            body = ((IteratorDecl)clbl).Body;
 0669          }
 670
 1884671          if (body != null) {
 942672            var c = new FillInDefaultLoopDecreases_Visitor(this, clbl);
 942673            c.Visit(body);
 942674          }
 942675        }
 102676      }
 677
 612678      foreach (var module in prog.Modules()) {
 306679        foreach (var iter in ModuleDefinition.AllIteratorDecls(module.TopLevelDecls)) {
 0680          reporter.Info(MessageSource.Resolver, iter.tok, Printer.IteratorClassToString(Reporter.Options, iter));
 0681        }
 102682      }
 683
 612684      foreach (var module in prog.Modules()) {
 5202685        foreach (var rewriter in rewriters) {
 1632686          rewriter.PostDecreasesResolve(module);
 1632687        }
 102688      }
 689
 690      // fill in other additional information
 612691      foreach (var module in prog.Modules()) {
 3132692        foreach (var clbl in ModuleDefinition.AllItersAndCallables(module.TopLevelDecls)) {
 942693          Statement body = null;
 942694          if (clbl is ExtremeLemma) {
 0695            body = ((ExtremeLemma)clbl).PrefixLemma.Body;
 1884696          } else if (clbl is Method) {
 942697            body = ((Method)clbl).Body;
 942698          } else if (clbl is IteratorDecl) {
 0699            body = ((IteratorDecl)clbl).Body;
 0700          }
 701
 1884702          if (body != null) {
 942703            var c = new ReportOtherAdditionalInformation_Visitor(this);
 942704            c.Visit(body);
 942705          }
 942706        }
 102707      }
 708
 709      // Determine, for each function, whether someone tries to adjust its fuel parameter
 612710      foreach (var module in prog.Modules()) {
 102711        CheckForFuelAdjustments(module.tok, module.Attributes, module);
 3132712        foreach (var clbl in ModuleDefinition.AllItersAndCallables(module.TopLevelDecls)) {
 942713          Statement body = null;
 1884714          if (clbl is Method) {
 942715            body = ((Method)clbl).Body;
 942716            CheckForFuelAdjustments(clbl.Tok, ((Method)clbl).Attributes, module);
 942717          } else if (clbl is IteratorDecl) {
 0718            body = ((IteratorDecl)clbl).Body;
 0719            CheckForFuelAdjustments(clbl.Tok, ((IteratorDecl)clbl).Attributes, module);
 0720          } else if (clbl is Function) {
 0721            CheckForFuelAdjustments(clbl.Tok, ((Function)clbl).Attributes, module);
 0722            var c = new FuelAdjustment_Visitor(this);
 0723            var bodyExpr = ((Function)clbl).Body;
 0724            if (bodyExpr != null) {
 0725              c.Visit(bodyExpr, new FuelAdjustment_Context(module));
 0726            }
 0727          }
 728
 1884729          if (body != null) {
 942730            var c = new FuelAdjustment_Visitor(this);
 942731            c.Visit(body, new FuelAdjustment_Context(module));
 942732          }
 942733        }
 102734      }
 735
 102736      Type.DisableScopes();
 102737      CheckDupModuleNames(prog);
 738
 612739      foreach (var module in prog.Modules()) {
 5202740        foreach (var rewriter in rewriters) {
 1632741          rewriter.PostResolve(module);
 1632742        }
 102743      }
 744
 5202745      foreach (var rewriter in rewriters) {
 1632746        rewriter.PostResolve(prog);
 1632747      }
 112748    }
 749
 750
 751
 112752    private void ResolveValuetypeDecls() {
 112753      moduleInfo = systemNameInfo;
 2688754      foreach (var valueTypeDecl in valuetypeDecls) {
 6720755        foreach (var kv in valueTypeDecl.Members) {
 1680756          if (kv.Value is Function function) {
 224757            ResolveFunctionSignature(function);
 224758            CallGraphBuilder.VisitFunction(function, reporter);
 1456759          } else if (kv.Value is Method method) {
 0760            ResolveMethodSignature(method);
 0761            CallGraphBuilder.VisitMethod(method, reporter);
 0762          }
 1456763        }
 784764      }
 112765    }
 766
 767    /// <summary>
 768    /// Resolves the module definition.
 769    /// A return code of "false" is an indication of an error that may or may not have
 770    /// been reported in an error message. So, in order to figure out if m was successfully
 771    /// resolved, a caller has to check for both a change in error count and a "false"
 772    /// return value.
 773    /// </summary>
 214774    private bool ResolveModuleDefinition(ModuleDefinition m, ModuleSignature sig, bool isAnExport = false) {
 775      Contract.Requires(AllTypeConstraints.Count == 0);
 776      Contract.Ensures(AllTypeConstraints.Count == 0);
 777
 214778      sig.VisibilityScope.Augment(systemNameInfo.VisibilityScope);
 779      // make sure all imported modules were successfully resolved
 2091780      foreach (var d in m.TopLevelDecls) {
 483781        if (d is AliasModuleDecl || d is AbstractModuleDecl) {
 782          ModuleSignature importSig;
 0783          if (d is AliasModuleDecl) {
 0784            var alias = (AliasModuleDecl)d;
 0785            importSig = alias.TargetQId.Root != null ? alias.TargetQId.Root.Signature : alias.Signature;
 0786          } else {
 0787            importSig = ((AbstractModuleDecl)d).OriginalSignature;
 0788          }
 789
 0790          if (importSig.ModuleDef == null || !importSig.ModuleDef.SuccessfullyResolved) {
 0791            if (!m.IsEssentiallyEmptyModuleBody()) {
 792              // say something only if this will cause any testing to be omitted
 0793              reporter.Error(MessageSource.Resolver, d,
 0794                "not resolving module '{0}' because there were errors in resolving its import '{1}'", m.Name, d.Name);
 0795            }
 796
 0797            return false;
 798          }
 483799        } else if (d is LiteralModuleDecl) {
 0800          var nested = (LiteralModuleDecl)d;
 0801          if (!nested.ModuleDef.SuccessfullyResolved) {
 0802            if (!m.IsEssentiallyEmptyModuleBody()) {
 803              // say something only if this will cause any testing to be omitted
 0804              reporter.Error(MessageSource.Resolver, nested,
 0805                "not resolving module '{0}' because there were errors in resolving its nested module '{1}'", m.Name,
 0806                nested.Name);
 0807            }
 808
 0809            return false;
 810          }
 0811        }
 483812      }
 813
 814      // resolve
 214815      var oldModuleInfo = moduleInfo;
 214816      moduleInfo = MergeSignature(sig, systemNameInfo);
 214817      Type.PushScope(moduleInfo.VisibilityScope);
 214818      ResolveOpenedImports(moduleInfo, m, useCompileSignatures, this); // opened imports do not persist
 214819      var datatypeDependencies = new Graph<IndDatatypeDecl>();
 214820      var codatatypeDependencies = new Graph<CoDatatypeDecl>();
 214821      var allDeclarations = ModuleDefinition.AllDeclarationsAndNonNullTypeDecls(m.TopLevelDecls).ToList();
 214822      int prevErrorCount = reporter.Count(ErrorLevel.Error);
 214823      ResolveTopLevelDecls_Signatures(m, sig, allDeclarations, datatypeDependencies, codatatypeDependencies);
 214824      Contract.Assert(AllTypeConstraints.Count == 0); // signature resolution does not add any type constraints
 825
 214826      scope.PushMarker();
 214827      scope.AllowInstance = false;
 214828      ResolveAttributes(m, new ResolutionContext(new NoContext(m.EnclosingModule), false), true); // Must follow Resolve
 214829      scope.PopMarker();
 830
 428831      if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 214832        ResolveTopLevelDecls_Core(allDeclarations, datatypeDependencies, codatatypeDependencies, m.Name, isAnExport);
 214833      }
 834
 214835      Type.PopScope(moduleInfo.VisibilityScope);
 214836      moduleInfo = oldModuleInfo;
 214837      return true;
 214838    }
 839
 840    // Resolve the exports and detect cycles.
 112841    private void ResolveModuleExport(LiteralModuleDecl literalDecl, ModuleSignature sig) {
 112842      ModuleDefinition m = literalDecl.ModuleDef;
 112843      literalDecl.DefaultExport = sig;
 112844      Graph<ModuleExportDecl> exportDependencies = new Graph<ModuleExportDecl>();
 1143845      foreach (TopLevelDecl toplevel in m.TopLevelDecls) {
 269846        if (toplevel is ModuleExportDecl) {
 0847          ModuleExportDecl d = (ModuleExportDecl)toplevel;
 0848          exportDependencies.AddVertex(d);
 0849          foreach (IToken s in d.Extends) {
 850            ModuleExportDecl extend;
 0851            if (sig.ExportSets.TryGetValue(s.val, out extend)) {
 0852              d.ExtendDecls.Add(extend);
 0853              exportDependencies.AddEdge(d, extend);
 0854            } else {
 0855              reporter.Error(MessageSource.Resolver, s, s.val + " must be an export of " + m.Name + " to be extended");
 0856            }
 0857          }
 0858        }
 269859      }
 860
 861      // detect cycles in the extend
 112862      var cycleError = false;
 336863      foreach (var cycle in exportDependencies.AllCycles()) {
 0864        ReportCycleError(cycle, m => m.tok, m => m.Name, "module export contains a cycle");
 0865        cycleError = true;
 0866      }
 867
 112868      if (cycleError) {
 0869        return;
 870      } // give up on trying to resolve anything else
 871
 872      // fill in the exports for the extends.
 112873      List<ModuleExportDecl> sortedExportDecls = exportDependencies.TopologicallySortedComponents();
 112874      ModuleExportDecl defaultExport = null;
 875      TopLevelDecl defaultClass;
 876
 112877      sig.TopLevels.TryGetValue("_default", out defaultClass);
 112878      Contract.Assert(defaultClass is ClassDecl);
 112879      Contract.Assert(((ClassDecl)defaultClass).IsDefaultClass);
 112880      defaultClass.AddVisibilityScope(m.VisibilityScope, true);
 881
 336882      foreach (var d in sortedExportDecls) {
 883
 0884        defaultClass.AddVisibilityScope(d.ThisScope, true);
 885
 0886        foreach (var eexports in d.ExtendDecls.Select(e => e.Exports)) {
 0887          d.Exports.AddRange(eexports);
 0888        }
 889
 0890        if (d.ExtendDecls.Count == 0 && d.Exports.Count == 0) {
 891          // This is an empty export.  This is allowed, but unusual.  It could pop up, for example, if
 892          // someone temporary comments out everything that the export set provides/reveals.  However,
 893          // if the name of the export set coincides with something else that's declared at the top
 894          // level of the module, then this export declaration is more likely an error--the user probably
 895          // forgot the "provides" or "reveals" keyword.
 896          Dictionary<string, MemberDecl> members;
 897          MemberDecl member;
 898          // Top-level functions and methods are actually recorded as members of the _default class.  We look up the
 899          // export-set name there.  If the export-set name happens to coincide with some other top-level declaration,
 900          // then an error will already have been produced ("duplicate name of top-level declaration").
 0901          if (classMembers.TryGetValue((ClassDecl)defaultClass, out members) &&
 0902              members.TryGetValue(d.Name, out member)) {
 0903            reporter.Warning(MessageSource.Resolver, ErrorRegistry.NoneId, d.tok,
 0904              "note, this export set is empty (did you perhaps forget the 'provides' or 'reveals' keyword?)");
 0905          }
 0906        }
 907
 0908        foreach (ExportSignature export in d.Exports) {
 909
 910          // check to see if it is a datatype or a member or
 911          // static function or method in the enclosing module or its imports
 912          TopLevelDecl tdecl;
 913          MemberDecl member;
 914          TopLevelDecl cldecl;
 915
 0916          Declaration decl = null;
 0917          string name = export.Id;
 918
 0919          if (export.ClassId != null) {
 0920            if (!sig.TopLevels.TryGetValue(export.ClassId, out cldecl)) {
 0921              reporter.Error(MessageSource.Resolver, export.ClassIdTok, "'{0}' is not a top-level type declaration",
 0922                export.ClassId);
 0923              continue;
 924            }
 925
 0926            if (cldecl is ClassDecl && ((ClassDecl)cldecl).NonNullTypeDecl != null) {
 927              // cldecl is a possibly-null type (syntactically given with a question mark at the end)
 0928              reporter.Error(MessageSource.Resolver, export.ClassIdTok, "'{0}' is not a type that can declare members",
 0929                export.ClassId);
 0930              continue;
 931            }
 932
 0933            if (cldecl is NonNullTypeDecl) {
 934              // cldecl was given syntactically like the name of a class, but here it's referring to the corresponding n
 0935              cldecl = cldecl.ViewAsClass;
 0936            }
 937
 0938            var mt = cldecl as TopLevelDeclWithMembers;
 0939            if (mt == null) {
 0940              reporter.Error(MessageSource.Resolver, export.ClassIdTok, "'{0}' is not a type that can declare members",
 0941                export.ClassId);
 0942              continue;
 943            }
 944
 0945            var lmem = mt.Members.FirstOrDefault(l => l.Name == export.Id);
 0946            if (lmem == null) {
 0947              reporter.Error(MessageSource.Resolver, export.Tok, "No member '{0}' found in type '{1}'", export.Id,
 0948                export.ClassId);
 0949              continue;
 950            }
 951
 0952            decl = lmem;
 0953          } else if (sig.TopLevels.TryGetValue(name, out tdecl)) {
 0954            if (tdecl is ClassDecl && ((ClassDecl)tdecl).NonNullTypeDecl != null) {
 955              // cldecl is a possibly-null type (syntactically given with a question mark at the end)
 0956              var nn = ((ClassDecl)tdecl).NonNullTypeDecl;
 0957              Contract.Assert(nn != null);
 0958              reporter.Error(MessageSource.Resolver, export.Tok,
 0959                export.Opaque
 0960                  ? "Type '{1}' can only be revealed, not provided"
 0961                  : "Types '{0}' and '{1}' are exported together, which is accomplished by revealing the name '{0}'",
 0962                nn.Name, name);
 0963              continue;
 964            }
 965
 966            // Member of the enclosing module
 0967            decl = tdecl;
 0968          } else if (sig.StaticMembers.TryGetValue(name, out member)) {
 0969            decl = member;
 0970          } else if (sig.ExportSets.ContainsKey(name)) {
 0971            reporter.Error(MessageSource.Resolver, export.Tok,
 0972              "'{0}' is an export set and cannot be provided/revealed by another export set (did you intend to list it i
 0973              name);
 0974            continue;
 0975          } else {
 0976            reporter.Error(MessageSource.Resolver, export.Tok, "'{0}' must be a member of '{1}' to be exported", name,
 0977              m.Name);
 0978            continue;
 979          }
 980
 0981          if (!decl.CanBeExported()) {
 0982            reporter.Error(MessageSource.Resolver, export.Tok, "'{0}' is not a valid export of '{1}'", name, m.Name);
 0983            continue;
 984          }
 985
 0986          if (!export.Opaque && !decl.CanBeRevealed()) {
 0987            reporter.Error(MessageSource.Resolver, export.Tok,
 0988              "'{0}' cannot be revealed in an export. Use \"provides\" instead.", name);
 0989            continue;
 990          }
 991
 0992          export.Decl = decl;
 0993          if (decl is NonNullTypeDecl nntd) {
 0994            nntd.AddVisibilityScope(d.ThisScope, export.Opaque);
 0995            if (!export.Opaque) {
 0996              nntd.Class.AddVisibilityScope(d.ThisScope, export.Opaque);
 997              // add the anonymous constructor, if any
 0998              var anonymousConstructor = nntd.Class.Members.Find(mdecl => mdecl.Name == "_ctor");
 0999              if (anonymousConstructor != null) {
 01000                anonymousConstructor.AddVisibilityScope(d.ThisScope, false);
 01001              }
 01002            }
 01003          } else {
 01004            decl.AddVisibilityScope(d.ThisScope, export.Opaque);
 01005          }
 01006        }
 01007      }
 1008
 3361009      foreach (ModuleExportDecl decl in sortedExportDecls) {
 01010        if (decl.IsDefault) {
 01011          if (defaultExport == null) {
 01012            defaultExport = decl;
 01013          } else {
 01014            reporter.Error(MessageSource.Resolver, m.tok, "more than one default export set declared in module {0}",
 01015              m.Name);
 01016          }
 01017        }
 1018
 1019        // fill in export signature
 01020        ModuleSignature signature = decl.Signature;
 01021        if (signature != null) {
 01022          signature.ModuleDef = m;
 01023        }
 1024
 01025        foreach (var top in sig.TopLevels) {
 01026          if (!top.Value.CanBeExported() || !top.Value.IsVisibleInScope(signature.VisibilityScope)) {
 01027            continue;
 1028          }
 1029
 01030          if (!signature.TopLevels.ContainsKey(top.Key)) {
 01031            signature.TopLevels.Add(top.Key, top.Value);
 01032          }
 1033
 01034          if (top.Value is DatatypeDecl && top.Value.IsRevealedInScope(signature.VisibilityScope)) {
 01035            foreach (var ctor in ((DatatypeDecl)top.Value).Ctors) {
 01036              if (!signature.Ctors.ContainsKey(ctor.Name)) {
 01037                signature.Ctors.Add(ctor.Name, new Tuple<DatatypeCtor, bool>(ctor, false));
 01038              }
 01039            }
 01040          }
 01041        }
 1042
 01043        foreach (var mem in sig.StaticMembers.Where(t =>
 01044          t.Value.IsVisibleInScope(signature.VisibilityScope) && t.Value.CanBeExported())) {
 01045          if (!signature.StaticMembers.ContainsKey(mem.Key)) {
 01046            signature.StaticMembers.Add(mem.Key, (MemberDecl)mem.Value);
 01047          }
 01048        }
 01049      }
 1050
 1051      // set the default export set, if it exists
 1121052      if (defaultExport != null) {
 01053        literalDecl.DefaultExport = defaultExport.Signature;
 1121054      } else if (sortedExportDecls.Count > 0) {
 01055        literalDecl.DefaultExport = null;
 01056      }
 1057
 1058      // final pass to propagate visibility of exported imports
 1121059      var sigs = sortedExportDecls.Select(d => d.Signature).Concat1(sig);
 1060
 6721061      foreach (var s in sigs) {
 11431062        foreach (var decl in s.TopLevels) {
 2691063          if (decl.Value is ModuleDecl && !(decl.Value is ModuleExportDecl)) {
 01064            var modDecl = (ModuleDecl)decl.Value;
 01065            s.VisibilityScope.Augment(modDecl.AccessibleSignature().VisibilityScope);
 01066          }
 2691067        }
 1121068      }
 1069
 1121070      var exported = new HashSet<Tuple<Declaration, bool>>();
 1071
 1072      //some decls may not be set due to resolution errors
 3361073      foreach (var e in sortedExportDecls.SelectMany(e => e.Exports).Where(e => e.Decl != null)) {
 01074        var decl = e.Decl;
 01075        exported.Add(new Tuple<Declaration, bool>(decl, e.Opaque));
 01076        if (!e.Opaque && decl.CanBeRevealed()) {
 01077          exported.Add(new Tuple<Declaration, bool>(decl, true));
 01078          if (decl is NonNullTypeDecl nntd) {
 01079            exported.Add(new Tuple<Declaration, bool>(nntd.Class, true));
 01080          }
 01081        }
 1082
 01083        if (e.Opaque && (decl is DatatypeDecl || decl is TypeSynonymDecl)) {
 1084          // Datatypes and type synonyms are marked as _provided when they appear in any provided export.  If a
 1085          // declaration is never provided, then either it isn't visible outside the module at all or its whole
 1086          // definition is.  Datatype and type-synonym declarations undergo some inference from their definitions.
 1087          // Such inference should not be done for provided declarations, since different views of the module
 1088          // would then get different inferred properties.
 01089          decl.Attributes = new Attributes("_provided", new List<Expression>(), decl.Attributes);
 01090          reporter.Info(MessageSource.Resolver, decl.tok, "{:_provided}");
 01091        }
 01092      }
 1093
 1121094      Dictionary<RevealableTypeDecl, bool?> declScopes = new Dictionary<RevealableTypeDecl, bool?>();
 1121095      Dictionary<RevealableTypeDecl, bool?> modifies = new Dictionary<RevealableTypeDecl, bool?>();
 1096
 1097      //of all existing types, compute the minimum visibility of them for each exported declaration's
 1098      //body and signature
 3361099      foreach (var e in exported) {
 1100
 01101        declScopes.Clear();
 01102        modifies.Clear();
 1103
 01104        foreach (var typ in revealableTypes) {
 01105          declScopes.Add(typ, null);
 01106        }
 1107
 01108        foreach (var decl in sortedExportDecls) {
 01109          if (decl.Exports.Exists(ex => ex.Decl == e.Item1 && (e.Item2 || !ex.Opaque))) {
 1110            //if we are revealed, consider those exports where we are provided as well
 01111            var scope = decl.Signature.VisibilityScope;
 1112
 01113            foreach (var kv in declScopes) {
 01114              bool? isOpaque = kv.Value;
 01115              var typ = kv.Key;
 01116              if (!typ.AsTopLevelDecl.IsVisibleInScope(scope)) {
 01117                modifies[typ] = null;
 01118                continue;
 1119              }
 1120
 01121              if (isOpaque.HasValue && isOpaque.Value) {
 1122                //type is visible here, but known-opaque, so do nothing
 01123                continue;
 1124              }
 1125
 01126              modifies[typ] = !typ.AsTopLevelDecl.IsRevealedInScope(scope);
 01127            }
 1128
 01129            foreach (var kv in modifies) {
 01130              if (!kv.Value.HasValue) {
 01131                declScopes.Remove(kv.Key);
 01132              } else {
 01133                var exvis = declScopes[kv.Key];
 01134                if (exvis.HasValue) {
 01135                  declScopes[kv.Key] = exvis.Value || kv.Value.Value;
 01136                } else {
 01137                  declScopes[kv.Key] = kv.Value;
 01138                }
 01139              }
 01140            }
 1141
 01142            modifies.Clear();
 01143          }
 01144        }
 1145
 01146        VisibilityScope newscope = new VisibilityScope(e.Item1.Name);
 1147
 01148        foreach (var rt in declScopes) {
 01149          if (!rt.Value.HasValue) {
 01150            continue;
 1151          }
 1152
 01153          rt.Key.AsTopLevelDecl.AddVisibilityScope(newscope, rt.Value.Value);
 01154        }
 01155      }
 1121156    }
 1157
 1158    //check for export consistency by resolving internal modules
 1159    //this should be effect-free, as it only operates on clones
 1021160    private void CheckModuleExportConsistency(ModuleDefinition m) {
 1021161      var oldModuleInfo = moduleInfo;
 3061162      foreach (var exportDecl in m.TopLevelDecls.OfType<ModuleExportDecl>()) {
 1163
 01164        var prevErrors = reporter.Count(ErrorLevel.Error);
 1165
 01166        foreach (var export in exportDecl.Exports) {
 01167          if (export.Decl is MemberDecl member) {
 1168            // For classes and traits, the visibility test is performed on the corresponding non-null type
 01169            var enclosingType = member.EnclosingClass is ClassDecl cl && cl.NonNullTypeDecl != null
 01170              ? cl.NonNullTypeDecl
 01171              : member.EnclosingClass;
 01172            if (!enclosingType.IsVisibleInScope(exportDecl.Signature.VisibilityScope)) {
 01173              reporter.Error(MessageSource.Resolver, export.Tok,
 01174                "Cannot export type member '{0}' without providing its enclosing {1} '{2}'", member.Name,
 01175                member.EnclosingClass.WhatKind, member.EnclosingClass.Name);
 01176            } else if (member is Constructor &&
 01177                       !member.EnclosingClass.IsRevealedInScope(exportDecl.Signature.VisibilityScope)) {
 01178              reporter.Error(MessageSource.Resolver, export.Tok,
 01179                "Cannot export constructor '{0}' without revealing its enclosing {1} '{2}'", member.Name,
 01180                member.EnclosingClass.WhatKind, member.EnclosingClass.Name);
 01181            } else if (member is Field && !(member is ConstantField) &&
 01182                       !member.EnclosingClass.IsRevealedInScope(exportDecl.Signature.VisibilityScope)) {
 01183              reporter.Error(MessageSource.Resolver, export.Tok,
 01184                "Cannot export mutable field '{0}' without revealing its enclosing {1} '{2}'", member.Name,
 01185                member.EnclosingClass.WhatKind, member.EnclosingClass.Name);
 01186            }
 01187          }
 01188        }
 1189
 01190        var scope = exportDecl.Signature.VisibilityScope;
 01191        Cloner cloner = new ScopeCloner(scope);
 01192        var exportView = cloner.CloneModuleDefinition(m, m.NameNode);
 01193        if (Options.DafnyPrintExportedViews.Contains(exportDecl.FullName)) {
 01194          var wr = Options.OutputWriter;
 01195          wr.WriteLine("/* ===== export set {0}", exportDecl.FullName);
 01196          var pr = new Printer(wr, Options);
 01197          pr.PrintTopLevelDecls(exportView.TopLevelDecls, 0, null, null);
 01198          wr.WriteLine("*/");
 01199        }
 1200
 01201        if (reporter.Count(ErrorLevel.Error) != prevErrors) {
 01202          continue;
 1203        }
 1204
 01205        reporter = new ErrorReporterWrapper(reporter,
 01206          String.Format("Raised while checking export set {0}: ", exportDecl.Name));
 01207        var testSig = RegisterTopLevelDecls(exportView, true);
 1208        //testSig.Refines = refinementTransformer.RefinedSig;
 01209        ResolveModuleDefinition(exportView, testSig, true);
 01210        var wasError = reporter.Count(ErrorLevel.Error) > 0;
 01211        reporter = ((ErrorReporterWrapper)reporter).WrappedReporter;
 1212
 01213        if (wasError) {
 01214          reporter.Error(MessageSource.Resolver, exportDecl.tok, "This export set is not consistent: {0}", exportDecl.Na
 01215        }
 01216      }
 1217
 1021218      moduleInfo = oldModuleInfo;
 1021219    }
 1220
 1221    public class ModuleBindings {
 1222      private ModuleBindings parent;
 1223      private Dictionary<string, ModuleDecl> modules;
 1224      private Dictionary<string, ModuleBindings> bindings;
 1225
 4481226      public ModuleBindings(ModuleBindings p) {
 2241227        parent = p;
 2241228        modules = new Dictionary<string, ModuleDecl>();
 2241229        bindings = new Dictionary<string, ModuleBindings>();
 2241230      }
 1231
 1121232      public bool BindName(string name, ModuleDecl subModule, ModuleBindings b) {
 1121233        if (modules.ContainsKey(name)) {
 01234          return false;
 1121235        } else {
 1121236          modules.Add(name, subModule);
 1121237          bindings.Add(name, b);
 1121238          return true;
 1239        }
 1121240      }
 1241
 01242      public bool TryLookup(IToken name, out ModuleDecl m) {
 1243        Contract.Requires(name != null);
 01244        return TryLookupFilter(name, out m, l => true);
 01245      }
 1246
 01247      public bool TryLookupFilter(IToken name, out ModuleDecl m, Func<ModuleDecl, bool> filter) {
 1248        Contract.Requires(name != null);
 01249        if (modules.TryGetValue(name.val, out m) && filter(m)) {
 01250          return true;
 01251        } else if (parent != null) {
 01252          return parent.TryLookupFilter(name, out m, filter);
 01253        } else {
 01254          return false;
 1255        }
 01256      }
 1257
 1258      public IEnumerable<ModuleDecl> ModuleList {
 01259        get { return modules.Values; }
 1260      }
 1261
 01262      public ModuleBindings SubBindings(string name) {
 01263        ModuleBindings v = null;
 01264        bindings.TryGetValue(name, out v);
 01265        return v;
 01266      }
 1267    }
 1268
 1121269    private ModuleBindings BindModuleNames(ModuleDefinition moduleDecl, ModuleBindings parentBindings) {
 1121270      var bindings = new ModuleBindings(parentBindings);
 1271
 1272      // moduleDecl.PrefixNamedModules is a list of pairs like:
 1273      //     A.B.C  ,  module D { ... }
 1274      // We collect these according to the first component of the prefix, like so:
 1275      //     "A"   ->   (A.B.C  ,  module D { ... })
 1121276      var prefixNames = new Dictionary<string, List<Tuple<List<IToken>, LiteralModuleDecl>>>();
 3361277      foreach (var tup in moduleDecl.PrefixNamedModules) {
 01278        var id = tup.Item1[0].val;
 1279        List<Tuple<List<IToken>, LiteralModuleDecl>> prev;
 01280        if (!prefixNames.TryGetValue(id, out prev)) {
 01281          prev = new List<Tuple<List<IToken>, LiteralModuleDecl>>();
 01282        }
 1283
 01284        prev.Add(tup);
 01285        prefixNames[id] = prev;
 01286      }
 1287
 1121288      moduleDecl.PrefixNamedModules.Clear();
 1289
 1290      // First, register all literal modules, and transferring their prefix-named modules downwards
 11431291      foreach (var tld in moduleDecl.TopLevelDecls) {
 2691292        if (tld is LiteralModuleDecl) {
 01293          var subdecl = (LiteralModuleDecl)tld;
 1294          // Transfer prefix-named modules downwards into the sub-module
 1295          List<Tuple<List<IToken>, LiteralModuleDecl>> prefixModules;
 01296          if (prefixNames.TryGetValue(subdecl.Name, out prefixModules)) {
 01297            prefixNames.Remove(subdecl.Name);
 01298            prefixModules = prefixModules.ConvertAll(ShortenPrefix);
 01299          } else {
 01300            prefixModules = null;
 01301          }
 1302
 01303          BindModuleName_LiteralModuleDecl(subdecl, prefixModules, bindings);
 01304        }
 2691305      }
 1306
 1307      // Next, add new modules for any remaining entries in "prefixNames".
 3361308      foreach (var entry in prefixNames) {
 01309        var name = entry.Key;
 01310        var prefixNamedModules = entry.Value;
 01311        var tok = prefixNamedModules.First().Item1[0];
 01312        var modDef = new ModuleDefinition(tok.ToRange(), new Name(tok.ToRange(), name), new List<IToken>(), false, false
 01313          true, true);
 1314        // Every module is expected to have a default class, so we create and add one now
 01315        var defaultClass = new DefaultClassDecl(modDef, new List<MemberDecl>());
 01316        modDef.TopLevelDecls.Add(defaultClass);
 1317        // Add the new module to the top-level declarations of its parent and then bind its names as usual
 01318        var subdecl = new LiteralModuleDecl(modDef, moduleDecl);
 01319        moduleDecl.TopLevelDecls.Add(subdecl);
 01320        BindModuleName_LiteralModuleDecl(subdecl, prefixNamedModules.ConvertAll(ShortenPrefix), bindings);
 01321      }
 1322
 1323      // Finally, go through import declarations (that is, AbstractModuleDecl's and AliasModuleDecl's).
 11431324      foreach (var tld in moduleDecl.TopLevelDecls) {
 2691325        if (tld is AbstractModuleDecl || tld is AliasModuleDecl) {
 01326          var subdecl = (ModuleDecl)tld;
 01327          if (bindings.BindName(subdecl.Name, subdecl, null)) {
 1328            // the add was successful
 01329          } else {
 1330            // there's already something with this name
 1331            ModuleDecl prevDecl;
 01332            var yes = bindings.TryLookup(subdecl.tok, out prevDecl);
 01333            Contract.Assert(yes);
 01334            if (prevDecl is AbstractModuleDecl || prevDecl is AliasModuleDecl) {
 01335              reporter.Error(MessageSource.Resolver, subdecl.tok, "Duplicate name of import: {0}", subdecl.Name);
 01336            } else if (tld is AliasModuleDecl importDecl && importDecl.Opened && importDecl.TargetQId.Path.Count == 1 &&
 01337                       importDecl.Name == importDecl.TargetQId.rootName()) {
 01338              importDecl.ShadowsLiteralModule = true;
 01339            } else {
 01340              reporter.Error(MessageSource.Resolver, subdecl.tok,
 01341                "Import declaration uses same name as a module in the same scope: {0}", subdecl.Name);
 01342            }
 01343          }
 01344        }
 2691345      }
 1346
 1121347      return bindings;
 1121348    }
 1349
 01350    private Tuple<List<IToken>, LiteralModuleDecl> ShortenPrefix(Tuple<List<IToken>, LiteralModuleDecl> tup) {
 1351      Contract.Requires(tup.Item1.Count != 0);
 01352      var rest = tup.Item1.GetRange(1, tup.Item1.Count - 1);
 01353      return new Tuple<List<IToken>, LiteralModuleDecl>(rest, tup.Item2);
 01354    }
 1355
 1356    private void BindModuleName_LiteralModuleDecl(LiteralModuleDecl litmod,
 01357      List<Tuple<List<IToken>, LiteralModuleDecl>> /*?*/ prefixModules, ModuleBindings parentBindings) {
 1358      Contract.Requires(litmod != null);
 1359      Contract.Requires(parentBindings != null);
 1360
 1361      // Transfer prefix-named modules downwards into the sub-module
 01362      if (prefixModules != null) {
 01363        foreach (var tup in prefixModules) {
 01364          if (tup.Item1.Count == 0) {
 01365            tup.Item2.ModuleDef.EnclosingModule =
 01366              litmod.ModuleDef; // change the parent, now that we have found the right parent module for the prefix-name
 01367            var sm = new LiteralModuleDecl(tup.Item2.ModuleDef,
 01368              litmod.ModuleDef); // this will create a ModuleDecl with the right parent
 01369            litmod.ModuleDef.TopLevelDecls.Add(sm);
 01370          } else {
 01371            litmod.ModuleDef.PrefixNamedModules.Add(tup);
 01372          }
 01373        }
 01374      }
 1375
 01376      var bindings = BindModuleNames(litmod.ModuleDef, parentBindings);
 01377      if (!parentBindings.BindName(litmod.Name, litmod, bindings)) {
 01378        reporter.Error(MessageSource.Resolver, litmod.tok, "Duplicate module name: {0}", litmod.Name);
 01379      }
 01380    }
 1381
 1382    private bool ResolveQualifiedModuleIdRootRefines(ModuleDefinition context, ModuleBindings bindings, ModuleQualifiedI
 01383      out ModuleDecl result) {
 01384      Contract.Assert(qid != null);
 01385      IToken root = qid.Path[0].StartToken;
 01386      result = null;
 01387      bool res = bindings.TryLookupFilter(root, out result, m => m.EnclosingModuleDefinition != context);
 01388      qid.Root = result;
 01389      return res;
 01390    }
 1391
 1392    // Find a matching module for the root of the QualifiedId, ignoring
 1393    // (a) the module (context) itself and (b) any local imports
 1394    // The latter is so that if one writes 'import A`E  import F = A`F' the second A does not
 1395    // resolve to the alias produced by the first import
 1396    private bool ResolveQualifiedModuleIdRootImport(AliasModuleDecl context, ModuleBindings bindings, ModuleQualifiedId 
 01397      out ModuleDecl result) {
 01398      Contract.Assert(qid != null);
 01399      IToken root = qid.Path[0].StartToken;
 01400      result = null;
 01401      bool res = bindings.TryLookupFilter(root, out result,
 01402        m => context != m && ((context.EnclosingModuleDefinition == m.EnclosingModuleDefinition && context.Exports.Count
 01403      qid.Root = result;
 01404      return res;
 01405    }
 1406
 1407    private bool ResolveQualifiedModuleIdRootAbstract(AbstractModuleDecl context, ModuleBindings bindings, ModuleQualifi
 01408      out ModuleDecl result) {
 01409      Contract.Assert(qid != null);
 01410      IToken root = qid.Path[0].StartToken;
 01411      result = null;
 01412      bool res = bindings.TryLookupFilter(root, out result,
 01413        m => context != m && ((context.EnclosingModuleDefinition == m.EnclosingModuleDefinition && context.Exports.Count
 01414      qid.Root = result;
 01415      return res;
 01416    }
 1417
 1418    private void ProcessDependenciesDefinition(ModuleDecl decl, ModuleDefinition m, ModuleBindings bindings,
 1121419      Graph<ModuleDecl> dependencies) {
 1121420      Contract.Assert(decl is LiteralModuleDecl);
 1121421      if (m.RefinementQId != null) {
 1422        ModuleDecl other;
 01423        bool res = ResolveQualifiedModuleIdRootRefines(((LiteralModuleDecl)decl).ModuleDef, bindings, m.RefinementQId, o
 01424        if (!res) {
 01425          reporter.Error(MessageSource.Resolver, m.RefinementQId.rootToken(),
 01426            $"module {m.RefinementQId.ToString()} named as refinement base does not exist");
 01427        } else if (other is LiteralModuleDecl && ((LiteralModuleDecl)other).ModuleDef == m) {
 01428          reporter.Error(MessageSource.Resolver, m.RefinementQId.rootToken(), "module cannot refine itself: {0}",
 01429            m.RefinementQId.ToString());
 01430        } else {
 01431          Contract.Assert(other != null); // follows from postcondition of TryGetValue
 01432          dependencies.AddEdge(decl, other);
 01433        }
 01434      }
 1435
 11431436      foreach (var toplevel in m.TopLevelDecls) {
 2691437        if (toplevel is ModuleDecl) {
 01438          var d = (ModuleDecl)toplevel;
 01439          dependencies.AddEdge(decl, d);
 01440          var subbindings = bindings.SubBindings(d.Name);
 01441          ProcessDependencies(d, subbindings ?? bindings, dependencies);
 01442          if (!m.IsAbstract && d is AbstractModuleDecl && ((AbstractModuleDecl)d).QId.Root != null) {
 01443            reporter.Error(MessageSource.Resolver, d.tok,
 01444              "The abstract import named {0} (using :) may only be used in an abstract module declaration",
 01445              d.Name);
 01446          }
 01447        }
 2691448      }
 1121449    }
 1450
 1121451    private void ProcessDependencies(ModuleDecl moduleDecl, ModuleBindings bindings, Graph<ModuleDecl> dependencies) {
 1121452      dependencies.AddVertex(moduleDecl);
 2241453      if (moduleDecl is LiteralModuleDecl) {
 1121454        ProcessDependenciesDefinition(moduleDecl, ((LiteralModuleDecl)moduleDecl).ModuleDef, bindings, dependencies);
 1121455      } else if (moduleDecl is AliasModuleDecl) {
 01456        var alias = moduleDecl as AliasModuleDecl;
 1457        ModuleDecl root;
 1458        // TryLookupFilter works outward, looking for a match to the filter for
 1459        // each enclosing module.
 01460        if (!ResolveQualifiedModuleIdRootImport(alias, bindings, alias.TargetQId, out root)) {
 1461          //        if (!bindings.TryLookupFilter(alias.TargetQId.rootToken(), out root, m => alias != m)
 01462          reporter.Error(MessageSource.Resolver, alias.tok, ModuleNotFoundErrorMessage(0, alias.TargetQId.Path));
 01463        } else {
 01464          dependencies.AddEdge(moduleDecl, root);
 01465        }
 01466      } else if (moduleDecl is AbstractModuleDecl) {
 01467        var abs = moduleDecl as AbstractModuleDecl;
 1468        ModuleDecl root;
 01469        if (!ResolveQualifiedModuleIdRootAbstract(abs, bindings, abs.QId, out root)) {
 1470          //if (!bindings.TryLookupFilter(abs.QId.rootToken(), out root,
 1471          //  m => abs != m && (((abs.EnclosingModuleDefinition == m.EnclosingModuleDefinition) && (abs.Exports.Count ==
 01472          reporter.Error(MessageSource.Resolver, abs.tok, ModuleNotFoundErrorMessage(0, abs.QId.Path));
 01473        } else {
 01474          dependencies.AddEdge(moduleDecl, root);
 01475        }
 01476      }
 1121477    }
 1478
 01479    private static string ModuleNotFoundErrorMessage(int i, List<Name> path, string tail = "") {
 1480      Contract.Requires(path != null);
 1481      Contract.Requires(0 <= i && i < path.Count);
 01482      return "module " + path[i].Value + " does not exist" +
 01483             (1 < path.Count
 01484               ? " (position " + i.ToString() + " in path " + Util.Comma(".", path, x => x.Value) + ")" + tail
 01485               : "");
 01486    }
 1487
 1488    private static bool EquivIfPresent<T1, T2>(Dictionary<T1, T2> dic, T1 key, T2 val)
 26431489      where T2 : class {
 1490      T2 val2;
 26431491      if (dic.TryGetValue(key, out val2)) {
 01492        return val.Equals(val2);
 1493      }
 1494
 26431495      return true;
 26431496    }
 1497
 2141498    public static ModuleSignature MergeSignature(ModuleSignature m, ModuleSignature system) {
 1499      Contract.Requires(m != null);
 1500      Contract.Requires(system != null);
 2141501      var info = new ModuleSignature();
 1502      // add the system-declared information, among which we know there are no duplicates
 143341503      foreach (var kv in system.TopLevels) {
 45641504        info.TopLevels.Add(kv.Key, kv.Value);
 45641505      }
 1506
 21361507      foreach (var kv in system.Ctors) {
 4981508        info.Ctors.Add(kv.Key, kv.Value);
 4981509      }
 1510
 6421511      foreach (var kv in system.StaticMembers) {
 01512        info.StaticMembers.Add(kv.Key, kv.Value);
 01513      }
 1514
 1515      // add for the module itself
 20911516      foreach (var kv in m.TopLevels) {
 4831517        if (info.TopLevels.TryGetValue(kv.Key, out var infoValue)) {
 01518          if (infoValue != kv.Value) {
 1519            // This only happens if one signature contains the name C as a class C (because it
 1520            // provides C) and the other signature contains the name C as a non-null type decl
 1521            // (because it reveals C and C?). The merge output will contain the non-null type decl
 1522            // for the key (and we expect the mapping "C? -> class C" to be placed in the
 1523            // merge output as well, by the end of this loop).
 01524            if (infoValue is ClassDecl) {
 01525              var cd = (ClassDecl)infoValue;
 01526              Contract.Assert(cd.NonNullTypeDecl == kv.Value);
 01527              info.TopLevels[kv.Key] = kv.Value;
 01528            } else if (kv.Value is ClassDecl) {
 01529              var cd = (ClassDecl)kv.Value;
 01530              Contract.Assert(cd.NonNullTypeDecl == infoValue);
 1531              // info.TopLevel[kv.Key] already has the right value
 01532            } else {
 01533              Contract.Assert(false); // unexpected
 01534            }
 1535
 01536            continue;
 1537          }
 01538        }
 1539
 4831540        info.TopLevels[kv.Key] = kv.Value;
 4831541      }
 1542
 24241543      foreach (var kv in m.Ctors) {
 5941544        Contract.Assert(EquivIfPresent(info.Ctors, kv.Key, kv.Value));
 5941545        info.Ctors[kv.Key] = kv.Value;
 5941546      }
 1547
 67891548      foreach (var kv in m.StaticMembers) {
 20491549        Contract.Assert(EquivIfPresent(info.StaticMembers, kv.Key, kv.Value));
 20491550        info.StaticMembers[kv.Key] = kv.Value;
 20491551      }
 1552
 2141553      info.IsAbstract = m.IsAbstract;
 2141554      info.VisibilityScope = new VisibilityScope();
 2141555      info.VisibilityScope.Augment(m.VisibilityScope);
 2141556      info.VisibilityScope.Augment(system.VisibilityScope);
 2141557      return info;
 2141558    }
 1559
 1560    public static void ResolveOpenedImports(ModuleSignature sig, ModuleDefinition moduleDef, bool useCompileSignatures,
 2141561      Resolver resolver) {
 2141562      var declarations = sig.TopLevels.Values.ToList<TopLevelDecl>();
 2141563      var importedSigs = new HashSet<ModuleSignature>() { sig };
 1564
 2141565      var topLevelDeclReplacements = new List<TopLevelDecl>();
 157831566      foreach (var top in declarations) {
 50471567        if (top is ModuleDecl md && md.Opened) {
 01568          ResolveOpenedImportsWorker(sig, moduleDef, (ModuleDecl)top, importedSigs, useCompileSignatures, out var topLev
 01569          if (topLevelDeclReplacement != null) {
 01570            topLevelDeclReplacements.Add(topLevelDeclReplacement);
 01571          }
 01572        }
 50471573      }
 6421574      foreach (var topLevelDeclReplacement in topLevelDeclReplacements) {
 01575        if (sig.TopLevels.GetValueOrDefault(topLevelDeclReplacement.Name) is ModuleDecl moduleDecl) {
 01576          sig.ShadowedImportedModules[topLevelDeclReplacement.Name] = moduleDecl;
 01577        }
 01578        sig.TopLevels[topLevelDeclReplacement.Name] = topLevelDeclReplacement;
 01579      }
 1580
 4281581      if (resolver != null) {
 1582        //needed because ResolveOpenedImports is used statically for a refinement check
 2141583        if (sig.TopLevels["_default"] is AmbiguousTopLevelDecl) {
 01584          Contract.Assert(sig.TopLevels["_default"].WhatKind == "class");
 01585          var cl = new DefaultClassDecl(moduleDef, sig.StaticMembers.Values.ToList());
 01586          sig.TopLevels["_default"] = cl;
 01587          resolver.classMembers[cl] = cl.Members.ToDictionary(m => m.Name);
 01588        }
 2141589      }
 2141590    }
 1591
 01592    static TopLevelDecl ResolveAlias(TopLevelDecl dd) {
 01593      while (dd is AliasModuleDecl amd) {
 01594        dd = amd.TargetQId.Root;
 01595      }
 01596      return dd;
 01597    }
 1598
 1599    /// <summary>
 1600    /// Further populate "sig" with the accessible symbols from "im".
 1601    ///
 1602    /// Symbols declared locally in "moduleDef" take priority over any opened-import symbols, with one
 1603    /// exception:  for an "import opened M" where "M" contains a top-level symbol "M", unambiguously map the
 1604    /// name "M" to that top-level symbol in "sig". To achieve the "unambiguously" part, return the desired mapping
 1605    /// to the caller, and let the caller remap the symbol after all opened imports have been processed.
 1606    /// </summary>
 1607    static void ResolveOpenedImportsWorker(ModuleSignature sig, ModuleDefinition moduleDef, ModuleDecl im, HashSet<Modul
 01608      bool useCompileSignatures, out TopLevelDecl topLevelDeclReplacement) {
 1609
 01610      topLevelDeclReplacement = null;
 01611      var s = GetSignatureExt(im.AccessibleSignature(useCompileSignatures), useCompileSignatures);
 1612
 01613      if (importedSigs.Contains(s)) {
 01614        return; // we've already got these declarations
 1615      }
 1616
 01617      importedSigs.Add(s);
 1618
 1619      // top-level declarations:
 01620      foreach (var kv in s.TopLevels) {
 01621        if (!kv.Value.CanBeExported()) {
 01622          continue;
 1623        }
 1624
 01625        if (!sig.TopLevels.TryGetValue(kv.Key, out var d)) {
 01626          sig.TopLevels.Add(kv.Key, kv.Value);
 01627        } else if (d.EnclosingModuleDefinition == moduleDef) {
 01628          if (kv.Value.EnclosingModuleDefinition.DafnyName != kv.Key) {
 1629            // declarations in the importing module take priority over opened-import declarations
 01630          } else {
 1631            // As an exception to the rule, for an "import opened M" that contains a top-level symbol "M", unambiguously
 1632            // name "M" to that top-level symbol in "sig". To achieve the "unambiguously" part, return the desired mappi
 1633            // the caller, and let the caller remap the symbol after all opened imports have been processed.
 01634            topLevelDeclReplacement = kv.Value;
 01635          }
 01636        } else {
 01637          bool unambiguous = false;
 1638          // keep just one if they normalize to the same entity
 01639          if (d == kv.Value) {
 01640            unambiguous = true;
 01641          } else if (d is ModuleDecl || kv.Value is ModuleDecl) {
 01642            var dd = ResolveAlias(d);
 01643            var dk = ResolveAlias(kv.Value);
 01644            unambiguous = dd == dk;
 01645          } else {
 1646            // It's okay if "d" and "kv.Value" denote the same type. This can happen, for example,
 1647            // if both are type synonyms for "int".
 01648            var scope = Type.GetScope();
 01649            if (d.IsVisibleInScope(scope) && kv.Value.IsVisibleInScope(scope)) {
 01650              var dType = UserDefinedType.FromTopLevelDecl(d.tok, d);
 01651              var vType = UserDefinedType.FromTopLevelDecl(kv.Value.tok, kv.Value);
 01652              unambiguous = dType.Equals(vType, true);
 01653            }
 01654          }
 01655          if (!unambiguous) {
 01656            sig.TopLevels[kv.Key] = AmbiguousTopLevelDecl.Create(moduleDef, d, kv.Value);
 01657          }
 01658        }
 01659      }
 1660
 1661      // constructors:
 01662      foreach (var kv in s.Ctors) {
 01663        if (sig.Ctors.TryGetValue(kv.Key, out var pair)) {
 1664          // The same ctor can be imported from two different imports (e.g "diamond" imports), in which case,
 1665          // they are not duplicates.
 01666          if (!Object.ReferenceEquals(kv.Value.Item1, pair.Item1)) {
 1667            // mark it as a duplicate
 01668            sig.Ctors[kv.Key] = new Tuple<DatatypeCtor, bool>(pair.Item1, true);
 01669          }
 01670        } else {
 1671          // add new
 01672          sig.Ctors.Add(kv.Key, kv.Value);
 01673        }
 01674      }
 1675
 1676      // static members:
 01677      foreach (var kv in s.StaticMembers) {
 01678        if (!kv.Value.CanBeExported()) {
 01679          continue;
 1680        }
 1681
 01682        if (sig.StaticMembers.TryGetValue(kv.Key, out var md)) {
 01683          sig.StaticMembers[kv.Key] = AmbiguousMemberDecl.Create(moduleDef, md, kv.Value);
 01684        } else {
 1685          // add new
 01686          sig.StaticMembers.Add(kv.Key, kv.Value);
 01687        }
 01688      }
 01689    }
 1690
 3261691    ModuleSignature RegisterTopLevelDecls(ModuleDefinition moduleDef, bool useImports) {
 1692      Contract.Requires(moduleDef != null);
 3261693      var sig = new ModuleSignature();
 3261694      sig.ModuleDef = moduleDef;
 3261695      sig.IsAbstract = moduleDef.IsAbstract;
 3261696      sig.VisibilityScope = new VisibilityScope();
 3261697      sig.VisibilityScope.Augment(moduleDef.VisibilityScope);
 1698
 3261699      List<TopLevelDecl> declarations = moduleDef.TopLevelDecls;
 1700
 1701      // This is solely used to detect duplicates amongst the various e
 3261702      Dictionary<string, TopLevelDecl> toplevels = new Dictionary<string, TopLevelDecl>();
 1703      // Now add the things present
 3261704      var anonymousImportCount = 0;
 89311705      foreach (TopLevelDecl d in declarations) {
 26511706        Contract.Assert(d != null);
 1707
 45181708        if (d is RevealableTypeDecl) {
 18671709          revealableTypes.Add((RevealableTypeDecl)d);
 18671710        }
 1711
 1712        // register the class/datatype/module name
 26511713        {
 26511714          TopLevelDecl registerThisDecl = null;
 26511715          string registerUnderThisName = null;
 26511716          if (d is ModuleExportDecl export) {
 01717            if (sig.ExportSets.ContainsKey(d.Name)) {
 01718              reporter.Error(MessageSource.Resolver, d, "duplicate name of export set: {0}", d.Name);
 01719            } else {
 01720              sig.ExportSets[d.Name] = export;
 01721            }
 26511722          } else if (d is AliasModuleDecl importDecl && importDecl.ShadowsLiteralModule) {
 1723            // add under an anonymous name
 01724            registerThisDecl = d;
 01725            registerUnderThisName = string.Format("{0}#{1}", d.Name, anonymousImportCount);
 01726            anonymousImportCount++;
 26511727          } else if (toplevels.ContainsKey(d.Name)) {
 01728            reporter.Error(MessageSource.Resolver, d, "duplicate name of top-level declaration: {0}", d.Name);
 28751729          } else if (d is ClassDecl cl && cl.NonNullTypeDecl != null) {
 2241730            registerThisDecl = cl.NonNullTypeDecl;
 2241731            registerUnderThisName = d.Name;
 26511732          } else {
 24271733            registerThisDecl = d;
 24271734            registerUnderThisName = d.Name;
 24271735          }
 1736
 53021737          if (registerThisDecl != null) {
 26511738            toplevels[registerUnderThisName] = registerThisDecl;
 26511739            sig.TopLevels[registerUnderThisName] = registerThisDecl;
 26511740          }
 26511741        }
 26511742        if (d is ModuleDecl) {
 1743          // nothing to do
 33231744        } else if (d is TypeSynonymDecl) {
 1745          // nothing more to register
 26511746        } else if (d is NewtypeDecl || d is AbstractTypeDecl) {
 01747          var cl = (TopLevelDeclWithMembers)d;
 1748          // register the names of the type members
 01749          var members = new Dictionary<string, MemberDecl>();
 01750          classMembers.Add(cl, members);
 01751          RegisterMembers(moduleDef, cl, members);
 19791752        } else if (d is IteratorDecl) {
 01753          var iter = (IteratorDecl)d;
 1754
 01755          iter.Resolve(this);
 26411756        } else if (d is ClassDecl) {
 6621757          var cl = (ClassDecl)d;
 6621758          var preMemberErrs = reporter.Count(ErrorLevel.Error);
 1759
 1760          // register the names of the class members
 6621761          var members = new Dictionary<string, MemberDecl>();
 6621762          classMembers.Add(cl, members);
 6621763          RegisterMembers(moduleDef, cl, members);
 1764
 6621765          Contract.Assert(preMemberErrs != reporter.Count(ErrorLevel.Error) ||
 6621766                          !cl.Members.Except(members.Values).Any());
 1767
 8761768          if (cl.IsDefaultClass) {
 67891769            foreach (MemberDecl m in members.Values) {
 20491770              Contract.Assert(!m.HasStaticKeyword || m is ConstantField); // note, the IsStatic value isn't available ye
 40981771              if (m is Function || m is Method || m is ConstantField) {
 20491772                sig.StaticMembers[m.Name] = m;
 20491773              }
 1774
 20491775              if (toplevels.ContainsKey(m.Name)) {
 01776                reporter.Error(MessageSource.Resolver, m.tok,
 01777                  $"duplicate declaration for name {m.Name}");
 01778              }
 20491779            }
 2141780          }
 1781
 25121782        } else if (d is DatatypeDecl) {
 5331783          var dt = (DatatypeDecl)d;
 1784
 1785          // register the names of the constructors
 5331786          dt.ConstructorsByName = new();
 1787          // ... and of the other members
 5331788          var members = new Dictionary<string, MemberDecl>();
 5331789          classMembers.Add(dt, members);
 1790
 41731791          foreach (DatatypeCtor ctor in dt.Ctors) {
 8581792            if (ctor.Name.EndsWith("?")) {
 01793              reporter.Error(MessageSource.Resolver, ctor,
 01794                "a datatype constructor name is not allowed to end with '?'");
 8581795            } else if (dt.ConstructorsByName.ContainsKey(ctor.Name)) {
 01796              reporter.Error(MessageSource.Resolver, ctor, "Duplicate datatype constructor name: {0}", ctor.Name);
 8581797            } else {
 8581798              dt.ConstructorsByName.Add(ctor.Name, ctor);
 8581799              ctor.InheritVisibility(dt);
 1800
 1801              // create and add the query "method" (field, really)
 8581802              var queryName = ctor.NameNode.Append("?");
 8581803              var query = new DatatypeDiscriminator(ctor.RangeToken, queryName, SpecialField.ID.UseIdParam, "is_" + ctor
 8581804                ctor.IsGhost, Type.Bool, null);
 8581805              query.InheritVisibility(dt);
 8581806              query.EnclosingClass = dt; // resolve here
 8581807              members.Add(queryName.Value, query);
 8581808              ctor.QueryField = query;
 1809
 1810              // also register the constructor name globally
 1811              Tuple<DatatypeCtor, bool> pair;
 8581812              if (sig.Ctors.TryGetValue(ctor.Name, out pair)) {
 1813                // mark it as a duplicate
 01814                sig.Ctors[ctor.Name] = new Tuple<DatatypeCtor, bool>(pair.Item1, true);
 8581815              } else {
 1816                // add new
 8581817                sig.Ctors.Add(ctor.Name, new Tuple<DatatypeCtor, bool>(ctor, false));
 8581818              }
 8581819            }
 8581820          }
 1821
 1822          // add deconstructors now (that is, after the query methods have been added)
 41731823          foreach (DatatypeCtor ctor in dt.Ctors) {
 8581824            var formalsUsedInThisCtor = new HashSet<string>();
 8581825            var duplicates = new HashSet<Formal>();
 53761826            foreach (var formal in ctor.Formals) {
 9341827              MemberDecl previousMember = null;
 9341828              var localDuplicate = false;
 18681829              if (formal.HasName) {
 9341830                if (members.TryGetValue(formal.Name, out previousMember)) {
 01831                  localDuplicate = formalsUsedInThisCtor.Contains(formal.Name);
 01832                  if (localDuplicate) {
 01833                    reporter.Error(MessageSource.Resolver, ctor,
 01834                      "Duplicate use of deconstructor name in the same constructor: {0}", formal.Name);
 01835                    duplicates.Add(formal);
 01836                  } else if (previousMember is DatatypeDestructor) {
 1837                    // this is okay, if the destructor has the appropriate type; this will be checked later, after type 
 01838                  } else {
 01839                    reporter.Error(MessageSource.Resolver, ctor,
 01840                      "Name of deconstructor is used by another member of the datatype: {0}", formal.Name);
 01841                  }
 01842                }
 1843
 9341844                formalsUsedInThisCtor.Add(formal.Name);
 9341845              }
 1846
 1847              DatatypeDestructor dtor;
 9341848              if (!localDuplicate && previousMember is DatatypeDestructor) {
 1849                // a destructor with this name already existed in (a different constructor in) the datatype
 01850                dtor = (DatatypeDestructor)previousMember;
 01851                dtor.AddAnotherEnclosingCtor(ctor, formal);
 9341852              } else {
 1853                // either the destructor has no explicit name, or this constructor declared another destructor with this
 9341854                dtor = new DatatypeDestructor(formal.RangeToken, ctor, formal, new Name(formal.RangeToken, formal.Name),
 9341855                  formal.IsGhost, formal.Type, null);
 9341856                dtor.InheritVisibility(dt);
 9341857                dtor.EnclosingClass = dt; // resolve here
 18681858                if (formal.HasName && !localDuplicate && previousMember == null) {
 1859                  // the destructor has an explict name and there was no member at all with this name before
 9341860                  members.Add(formal.Name, dtor);
 9341861                }
 9341862              }
 1863
 9341864              ctor.Destructors.Add(dtor);
 9341865            }
 1866
 25741867            foreach (var duplicate in duplicates) {
 01868              ctor.Formals.Remove(duplicate);
 01869            }
 8581870          }
 1871
 1872          // finally, add any additional user-defined members
 5331873          RegisterMembers(moduleDef, dt, members);
 13171874        } else {
 7841875          Contract.Assert(d is ValuetypeDecl);
 7841876        }
 26511877      }
 1878
 1879      // Now, for each class, register its possibly-null type
 89311880      foreach (TopLevelDecl d in declarations) {
 28751881        if ((d as ClassDecl)?.NonNullTypeDecl != null) {
 2241882          var name = d.Name + "?";
 1883          TopLevelDecl prev;
 2241884          if (toplevels.TryGetValue(name, out prev)) {
 01885            reporter.Error(MessageSource.Resolver, d,
 01886              "a module that already contains a top-level declaration '{0}' is not allowed to declare a {1} '{2}'",
 01887              name, d.WhatKind, d.Name);
 2241888          } else {
 2241889            toplevels[name] = d;
 2241890            sig.TopLevels[name] = d;
 2241891          }
 2241892        }
 26511893      }
 1894
 3261895      return sig;
 3261896    }
 1897
 1898    void RegisterMembers(ModuleDefinition moduleDef, TopLevelDeclWithMembers cl,
 11951899      Dictionary<string, MemberDecl> members) {
 1900      Contract.Requires(moduleDef != null);
 1901      Contract.Requires(cl != null);
 1902      Contract.Requires(members != null);
 1903
 114121904      foreach (MemberDecl m in cl.Members) {
 52181905        if (!members.ContainsKey(m.Name)) {
 26091906          members.Add(m.Name, m);
 26091907          if (m is Constructor) {
 01908            Contract.Assert(cl is ClassDecl); // the parser ensures this condition
 01909            if (cl is TraitDecl) {
 01910              reporter.Error(MessageSource.Resolver, m.tok, "a trait is not allowed to declare a constructor");
 01911            } else {
 01912              ((ClassDecl)cl).HasConstructor = true;
 01913            }
 26091914          } else if (m is ExtremePredicate || m is ExtremeLemma) {
 01915            var extraName = m.NameNode.Append("#");
 1916            MemberDecl extraMember;
 01917            var cloner = new Cloner();
 01918            var formals = new List<Formal>();
 1919            Type typeOfK;
 01920            if ((m is ExtremePredicate && ((ExtremePredicate)m).KNat) ||
 01921                (m is ExtremeLemma && ((ExtremeLemma)m).KNat)) {
 01922              typeOfK = new UserDefinedType(m.tok, "nat", (List<Type>)null);
 01923            } else {
 01924              typeOfK = new BigOrdinalType();
 01925            }
 1926
 01927            var k = new ImplicitFormal(m.tok, "_k", typeOfK, true, false);
 01928            reporter.Info(MessageSource.Resolver, m.tok, string.Format("_k: {0}", k.Type));
 01929            formals.Add(k);
 01930            if (m is ExtremePredicate extremePredicate) {
 01931              formals.AddRange(extremePredicate.Formals.ConvertAll(f => cloner.CloneFormal(f, false)));
 1932
 01933              List<TypeParameter> tyvars = extremePredicate.TypeArgs.ConvertAll(cloner.CloneTypeParam);
 1934
 1935              // create prefix predicate
 01936              extremePredicate.PrefixPredicate = new PrefixPredicate(extremePredicate.RangeToken, extraName, extremePred
 01937                tyvars, k, formals,
 01938                extremePredicate.Req.ConvertAll(cloner.CloneAttributedExpr),
 01939                extremePredicate.Reads.ConvertAll(cloner.CloneFrameExpr),
 01940                extremePredicate.Ens.ConvertAll(cloner.CloneAttributedExpr),
 01941                new Specification<Expression>(new List<Expression>() { new IdentifierExpr(extremePredicate.tok, k.Name) 
 01942                cloner.CloneExpr(extremePredicate.Body),
 01943                null,
 01944                extremePredicate);
 01945              extraMember = extremePredicate.PrefixPredicate;
 01946            } else {
 01947              var extremeLemma = (ExtremeLemma)m;
 1948              // _k has already been added to 'formals', so append the original formals
 01949              formals.AddRange(extremeLemma.Ins.ConvertAll(f => cloner.CloneFormal(f, false)));
 1950              // prepend _k to the given decreases clause
 01951              var decr = new List<Expression>();
 01952              decr.Add(new IdentifierExpr(extremeLemma.tok, k.Name));
 01953              decr.AddRange(extremeLemma.Decreases.Expressions.ConvertAll(cloner.CloneExpr));
 1954              // Create prefix lemma.  Note that the body is not cloned, but simply shared.
 1955              // For a greatest lemma, the postconditions are filled in after the greatest lemma's postconditions have b
 1956              // For a least lemma, the preconditions are filled in after the least lemma's preconditions have been reso
 01957              var req = extremeLemma is GreatestLemma
 01958                ? extremeLemma.Req.ConvertAll(cloner.CloneAttributedExpr)
 01959                : new List<AttributedExpression>();
 01960              var ens = extremeLemma is GreatestLemma
 01961                ? new List<AttributedExpression>()
 01962                : extremeLemma.Ens.ConvertAll(cloner.CloneAttributedExpr);
 01963              extremeLemma.PrefixLemma = new PrefixLemma(extremeLemma.RangeToken, extraName, extremeLemma.HasStaticKeywo
 01964                extremeLemma.TypeArgs.ConvertAll(cloner.CloneTypeParam), k, formals, extremeLemma.Outs.ConvertAll(f => c
 01965                req, cloner.CloneSpecFrameExpr(extremeLemma.Mod), ens,
 01966                new Specification<Expression>(decr, null),
 01967                null, // Note, the body for the prefix method will be created once the call graph has been computed and 
 01968                cloner.CloneAttributes(extremeLemma.Attributes), extremeLemma);
 01969              extraMember = extremeLemma.PrefixLemma;
 01970            }
 1971
 01972            extraMember.InheritVisibility(m, false);
 01973            members.Add(extraName.Value, extraMember);
 26091974          } else if (m is Function f && f.ByMethodBody != null) {
 01975            RegisterByMethod(f, cl);
 01976          }
 26091977        } else if (m is Constructor && !((Constructor)m).HasName) {
 01978          reporter.Error(MessageSource.Resolver, m, "More than one anonymous constructor");
 01979        } else {
 01980          reporter.Error(MessageSource.Resolver, m, "Duplicate member name: {0}", m.Name);
 01981        }
 26091982      }
 11951983    }
 1984
 01985    void RegisterByMethod(Function f, TopLevelDeclWithMembers cl) {
 1986      Contract.Requires(f != null && f.ByMethodBody != null);
 1987
 01988      var tok = f.ByMethodTok;
 01989      var resultVar = f.Result ?? new Formal(tok, "#result", f.ResultType, false, false, null);
 01990      var r = Expression.CreateIdentExpr(resultVar);
 01991      var receiver = f.IsStatic ? (Expression)new StaticReceiverExpr(tok, cl, true) : new ImplicitThisExpr(tok);
 01992      var fn = new FunctionCallExpr(tok, f.Name, receiver, tok, tok, f.Formals.ConvertAll(Expression.CreateIdentExpr));
 01993      var post = new AttributedExpression(new BinaryExpr(tok, BinaryExpr.Opcode.Eq, r, fn));
 01994      var method = new Method(f.RangeToken, f.NameNode, f.HasStaticKeyword, false, f.TypeArgs,
 01995        f.Formals, new List<Formal>() { resultVar },
 01996        f.Req, new Specification<FrameExpression>(new List<FrameExpression>(), null), new List<AttributedExpression>() {
 01997        f.ByMethodBody, f.Attributes, null, true);
 01998      Contract.Assert(f.ByMethodDecl == null);
 01999      method.InheritVisibility(f);
 02000      method.FunctionFromWhichThisIsByMethodDecl = f;
 02001      f.ByMethodDecl = method;
 02002    }
 2003
 2004    private ModuleSignature MakeAbstractSignature(ModuleSignature p, string Name, int Height,
 2005      Dictionary<ModuleDefinition, ModuleSignature> mods,
 02006      Dictionary<ModuleDefinition, ModuleDefinition> compilationModuleClones) {
 2007      Contract.Requires(p != null);
 2008      Contract.Requires(Name != null);
 2009      Contract.Requires(mods != null);
 2010      Contract.Requires(compilationModuleClones != null);
 02011      var errCount = reporter.Count(ErrorLevel.Error);
 2012
 02013      var mod = new ModuleDefinition(RangeToken.NoToken, new Name(Name + ".Abs"), new List<IToken>(), true, true, null, 
 02014        false,
 02015        p.ModuleDef.IsToBeVerified, p.ModuleDef.IsToBeCompiled);
 02016      mod.Height = Height;
 02017      bool hasDefaultClass = false;
 02018      foreach (var kv in p.TopLevels) {
 02019        hasDefaultClass = kv.Value is DefaultClassDecl || hasDefaultClass;
 02020        if (!(kv.Value is NonNullTypeDecl)) {
 02021          var clone = CloneDeclaration(p.VisibilityScope, kv.Value, mod, mods, Name, compilationModuleClones);
 02022          mod.TopLevelDecls.Add(clone);
 02023        }
 02024      }
 2025
 02026      if (!hasDefaultClass) {
 02027        DefaultClassDecl cl = new DefaultClassDecl(mod, p.StaticMembers.Values.ToList());
 02028        mod.TopLevelDecls.Add(CloneDeclaration(p.VisibilityScope, cl, mod, mods, Name, compilationModuleClones));
 02029      }
 2030
 02031      var sig = RegisterTopLevelDecls(mod, true);
 02032      sig.Refines = p.Refines;
 02033      sig.CompileSignature = p;
 02034      sig.IsAbstract = p.IsAbstract;
 02035      mods.Add(mod, sig);
 02036      var good = ResolveModuleDefinition(mod, sig);
 02037      if (good && reporter.Count(ErrorLevel.Error) == errCount) {
 02038        mod.SuccessfullyResolved = true;
 02039      }
 2040
 02041      return sig;
 02042    }
 2043
 2044    TopLevelDecl CloneDeclaration(VisibilityScope scope, TopLevelDecl d, ModuleDefinition m,
 2045      Dictionary<ModuleDefinition, ModuleSignature> mods, string Name,
 02046      Dictionary<ModuleDefinition, ModuleDefinition> compilationModuleClones) {
 2047      Contract.Requires(d != null);
 2048      Contract.Requires(m != null);
 2049      Contract.Requires(mods != null);
 2050      Contract.Requires(Name != null);
 2051      Contract.Requires(compilationModuleClones != null);
 2052
 02053      if (d is AbstractModuleDecl) {
 02054        var abs = (AbstractModuleDecl)d;
 02055        var sig = MakeAbstractSignature(abs.OriginalSignature, Name + "." + abs.Name, abs.Height, mods,
 02056          compilationModuleClones);
 02057        var a = new AbstractModuleDecl(abs.RangeToken, abs.QId, abs.NameNode, m, abs.Opened, abs.Exports);
 02058        a.Signature = sig;
 02059        a.OriginalSignature = abs.OriginalSignature;
 02060        return a;
 02061      } else {
 02062        return new AbstractSignatureCloner(scope).CloneDeclaration(d, m);
 2063      }
 02064    }
 2065
 2066    // Returns the resolved Module declaration corresponding to the qualified module id
 2067    // Requires the root to have been resolved
 2068    // Issues an error and returns null if the path is not valid
 02069    public ModuleDecl ResolveModuleQualifiedId(ModuleDecl root, ModuleQualifiedId qid, ErrorReporter reporter) {
 2070
 2071      Contract.Requires(qid != null);
 2072      Contract.Requires(qid.Path.Count > 0);
 2073
 02074      List<Name> Path = qid.Path;
 02075      ModuleDecl decl = root;
 2076      ModuleSignature p;
 02077      for (int k = 1; k < Path.Count; k++) {
 02078        if (decl is LiteralModuleDecl) {
 02079          p = ((LiteralModuleDecl)decl).DefaultExport;
 02080          if (p == null) {
 02081            reporter.Error(MessageSource.Resolver, Path[k],
 02082              ModuleNotFoundErrorMessage(k, Path, $" because {decl.Name} does not have a default export"));
 02083            return null;
 2084          }
 02085        } else {
 02086          p = decl.Signature;
 02087        }
 2088
 02089        var tld = p.TopLevels.GetValueOrDefault(Path[k].Value, null);
 02090        if (!(tld is ModuleDecl dd)) {
 02091          if (decl.Signature.ModuleDef == null) {
 02092            reporter.Error(MessageSource.Resolver, Path[k],
 02093              ModuleNotFoundErrorMessage(k, Path, " because of previous error"));
 02094          } else {
 02095            reporter.Error(MessageSource.Resolver, Path[k], ModuleNotFoundErrorMessage(k, Path));
 02096          }
 02097          return null;
 2098        }
 2099
 2100        // Any aliases along the qualified path ought to be already resolved,
 2101        // else the modules are not being resolved in the right order
 02102        if (dd is AliasModuleDecl amd) {
 02103          Contract.Assert(amd.Signature != null);
 02104        }
 02105        decl = dd;
 02106      }
 2107
 02108      return decl;
 02109    }
 2110
 2111
 2112    public bool ResolveExport(ModuleDecl alias, ModuleDefinition parent, ModuleQualifiedId qid,
 02113      List<IToken> Exports, out ModuleSignature p, ErrorReporter reporter) {
 2114      Contract.Requires(qid != null);
 2115      Contract.Requires(qid.Path.Count > 0);
 2116      Contract.Requires(Exports != null);
 2117
 02118      ModuleDecl root = qid.Root;
 02119      ModuleDecl decl = ResolveModuleQualifiedId(root, qid, reporter);
 02120      if (decl == null) {
 02121        p = null;
 02122        return false;
 2123      }
 02124      p = decl.Signature;
 02125      if (Exports.Count == 0) {
 02126        if (p.ExportSets.Count == 0) {
 02127          if (decl is LiteralModuleDecl) {
 02128            p = ((LiteralModuleDecl)decl).DefaultExport;
 02129          } else {
 2130            // p is OK
 02131          }
 02132        } else {
 02133          var m = p.ExportSets.GetValueOrDefault(decl.Name, null);
 02134          if (m == null) {
 2135            // no default view is specified.
 02136            reporter.Error(MessageSource.Resolver, qid.rootToken(), "no default export set declared in module: {0}", dec
 02137            return false;
 2138          }
 02139          p = m.AccessibleSignature();
 02140        }
 02141      } else {
 2142        ModuleExportDecl pp;
 02143        if (decl.Signature.ExportSets.TryGetValue(Exports[0].val, out pp)) {
 02144          p = pp.AccessibleSignature();
 02145        } else {
 02146          reporter.Error(MessageSource.Resolver, Exports[0], "no export set '{0}' in module '{1}'", Exports[0].val, decl
 02147          p = null;
 02148          return false;
 2149        }
 2150
 02151        foreach (IToken export in Exports.Skip(1)) {
 02152          if (decl.Signature.ExportSets.TryGetValue(export.val, out pp)) {
 02153            Contract.Assert(Object.ReferenceEquals(p.ModuleDef, pp.Signature.ModuleDef));
 02154            ModuleSignature merged = MergeSignature(p, pp.Signature);
 02155            merged.ModuleDef = pp.Signature.ModuleDef;
 02156            if (p.CompileSignature != null) {
 02157              Contract.Assert(pp.Signature.CompileSignature != null);
 02158              merged.CompileSignature = MergeSignature(p.CompileSignature, pp.Signature.CompileSignature);
 02159            } else {
 02160              Contract.Assert(pp.Signature.CompileSignature == null);
 02161            }
 02162            p = merged;
 02163          } else {
 02164            reporter.Error(MessageSource.Resolver, export, "no export set {0} in module {1}", export.val, decl.Name);
 02165            p = null;
 02166            return false;
 2167          }
 02168        }
 02169      }
 02170      return true;
 02171    }
 2172
 3262173    public void RevealAllInScope(List<TopLevelDecl> declarations, VisibilityScope scope) {
 89312174      foreach (TopLevelDecl d in declarations) {
 26512175        d.AddVisibilityScope(scope, false);
 38462176        if (d is TopLevelDeclWithMembers) {
 11952177          var cl = (TopLevelDeclWithMembers)d;
 114122178          foreach (var mem in cl.Members) {
 52182179            if (!mem.ScopeIsInherited) {
 26092180              mem.AddVisibilityScope(scope, false);
 26092181            }
 26092182          }
 11952183          var nnd = (cl as ClassDecl)?.NonNullTypeDecl;
 14192184          if (nnd != null) {
 2242185            nnd.AddVisibilityScope(scope, false);
 2242186          }
 11952187        }
 26512188      }
 3262189    }
 2190
 2142191    public void ResolveTopLevelDecls_Signatures(ModuleDefinition def, ModuleSignature sig, List<TopLevelDecl/*!*/>/*!*/ 
 2192      Contract.Requires(declarations != null);
 2193      Contract.Requires(datatypeDependencies != null);
 2194      Contract.Requires(codatatypeDependencies != null);
 2142195      RevealAllInScope(declarations, def.VisibilityScope);
 2196
 2197      /* Augment the scoping environment for the current module*/
 20912198      foreach (TopLevelDecl d in declarations) {
 4832199        if (d is ModuleDecl && !(d is ModuleExportDecl)) {
 02200          var decl = (ModuleDecl)d;
 02201          moduleInfo.VisibilityScope.Augment(decl.AccessibleSignature().VisibilityScope);
 02202          sig.VisibilityScope.Augment(decl.AccessibleSignature().VisibilityScope);
 02203        }
 4832204      }
 2205      /*if (sig.Refines != null) {
 2206        moduleInfo.VisibilityScope.Augment(sig.Refines.VisibilityScope);
 2207        sig.VisibilityScope.Augment(sig.Refines.VisibilityScope);
 2208      }*/
 2209
 2142210      var typeRedirectionDependencies = new Graph<RedirectingTypeDecl>();  // this concerns the type directions, not the
 20912211      foreach (TopLevelDecl d in declarations) {
 4832212        Contract.Assert(d != null);
 4832213        allTypeParameters.PushMarker();
 4832214        ResolveTypeParameters(d.TypeArgs, true, d);
 4832215        if (d is TypeSynonymDecl) {
 02216          var dd = (TypeSynonymDecl)d;
 02217          ResolveType(dd.tok, dd.Rhs, dd, ResolveTypeOptionEnum.AllowPrefix, dd.TypeArgs);
 02218          dd.Rhs.ForeachTypeComponent(ty => {
 02219            var s = ty.AsRedirectingType;
 02220            if (s != null && s != dd) {
 02221              typeRedirectionDependencies.AddEdge(dd, s);
 02222            }
 02223          });
 4832224        } else if (d is NewtypeDecl) {
 02225          var dd = (NewtypeDecl)d;
 02226          ResolveType(dd.tok, dd.BaseType, dd, ResolveTypeOptionEnum.DontInfer, null);
 02227          dd.BaseType.ForeachTypeComponent(ty => {
 02228            var s = ty.AsRedirectingType;
 02229            if (s != null && s != dd) {
 02230              typeRedirectionDependencies.AddEdge(dd, s);
 02231            }
 02232          });
 02233          ResolveClassMemberTypes(dd);
 4832234        } else if (d is IteratorDecl) {
 02235          ResolveIteratorSignature((IteratorDecl)d);
 4832236        } else if (d is ModuleDecl) {
 02237          var decl = (ModuleDecl)d;
 02238          if (!def.IsAbstract && decl is AliasModuleDecl am && decl.Signature.IsAbstract) {
 02239            reporter.Error(MessageSource.Resolver, am.TargetQId.rootToken(), "a compiled module ({0}) is not allowed to 
 02240          }
 7522241        } else if (d is DatatypeDecl) {
 2692242          var dd = (DatatypeDecl)d;
 2692243          ResolveCtorTypes(dd, datatypeDependencies, codatatypeDependencies);
 2692244          ResolveClassMemberTypes(dd);
 4832245        } else {
 2142246          ResolveClassMemberTypes((TopLevelDeclWithMembers)d);
 2142247        }
 4832248        allTypeParameters.PopMarker();
 4832249      }
 2250
 2251      // Resolve the parent-trait types and fill in .ParentTraitHeads
 2142252      var prevErrorCount = reporter.Count(ErrorLevel.Error);
 2142253      var parentRelation = new Graph<TopLevelDeclWithMembers>();
 20912254      foreach (TopLevelDecl d in declarations) {
 9662255        if (d is TopLevelDeclWithMembers cl) {
 4832256          ResolveParentTraitTypes(cl, parentRelation);
 4832257        }
 4832258      }
 2259      // Check for cycles among parent traits
 6422260      foreach (var cycle in parentRelation.AllCycles()) {
 02261        ReportCycleError(cycle, m => m.tok, m => m.Name, "trait definitions contain a cycle");
 02262      }
 4282263      if (prevErrorCount == reporter.Count(ErrorLevel.Error)) {
 2264        // Register the trait members in the classes that inherit them
 20912265        foreach (TopLevelDecl d in declarations) {
 9662266          if (d is TopLevelDeclWithMembers cl) {
 4832267            RegisterInheritedMembers(cl);
 4832268          }
 4832269        }
 2142270      }
 4282271      if (prevErrorCount == reporter.Count(ErrorLevel.Error)) {
 2272        // Now that all traits have been resolved, let classes inherit the trait members
 20912273        foreach (var d in declarations) {
 9662274          if (d is TopLevelDeclWithMembers cl) {
 4832275            InheritedTraitMembers(cl);
 4832276          }
 4832277        }
 2142278      }
 2279
 2280      // perform acyclicity test on type synonyms
 6422281      foreach (var cycle in typeRedirectionDependencies.AllCycles()) {
 02282        ReportCycleError(cycle, rtd => rtd.tok, rtd => rtd.Name, "cycle among redirecting types (newtypes, subset types,
 02283      }
 2142284    }
 2285
 02286    public static readonly List<NativeType> NativeTypes = new List<NativeType>() {
 02287      new NativeType("byte", 0, 0x100, 8, NativeType.Selection.Byte),
 02288      new NativeType("sbyte", -0x80, 0x80, 0, NativeType.Selection.SByte),
 02289      new NativeType("ushort", 0, 0x1_0000, 16, NativeType.Selection.UShort),
 02290      new NativeType("short", -0x8000, 0x8000, 0, NativeType.Selection.Short),
 02291      new NativeType("uint", 0, 0x1_0000_0000, 32, NativeType.Selection.UInt),
 02292      new NativeType("int", -0x8000_0000, 0x8000_0000, 0, NativeType.Selection.Int),
 02293      new NativeType("number", -0x1f_ffff_ffff_ffff, 0x20_0000_0000_0000, 0, NativeType.Selection.Number),  // JavaScrip
 02294      new NativeType("ulong", 0, new BigInteger(0x1_0000_0000) * new BigInteger(0x1_0000_0000), 64, NativeType.Selection
 02295      new NativeType("long", Int64.MinValue, 0x8000_0000_0000_0000, 0, NativeType.Selection.Long),
 02296    };
 2297
 2298    public void ResolveTopLevelDecls_Core(List<TopLevelDecl> declarations,
 2299      Graph<IndDatatypeDecl> datatypeDependencies, Graph<CoDatatypeDecl> codatatypeDependencies,
 3262300      string moduleName, bool isAnExport = false) {
 2301
 2302      Contract.Requires(declarations != null);
 2303      Contract.Requires(cce.NonNullElements(datatypeDependencies.GetVertices()));
 2304      Contract.Requires(cce.NonNullElements(codatatypeDependencies.GetVertices()));
 2305      Contract.Requires(AllTypeConstraints.Count == 0);
 2306
 2307      Contract.Ensures(AllTypeConstraints.Count == 0);
 2308
 3262309      int prevErrorCount = reporter.Count(ErrorLevel.Error);
 2310
 2311      // ---------------------------------- Pass 0 ----------------------------------
 2312      // This pass:
 2313      // * resolves names, introduces (and may solve) type constraints
 2314      // * checks that all types were properly inferred
 2315      // * fills in .ResolvedOp fields
 2316      // * perform substitution for DefaultValueExpression's
 2317      // ----------------------------------------------------------------------------
 2318
 3262319      if (Options.Get(CommonOptionBag.TypeSystemRefresh)) {
 2320        // Resolve all names and infer types.
 02321        var preTypeResolver = new PreTypeResolver(this);
 02322        preTypeResolver.ResolveDeclarations(declarations, moduleName);
 2323
 02324        if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 02325          var u = new UnderspecificationDetector(this);
 02326          u.Check(declarations);
 02327        }
 2328
 02329        if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 02330          new PreTypeToTypeVisitor().VisitDeclarations(declarations);
 02331        }
 2332
 3262333      } else {
 2334        // Resolve all names and infer types. These two are done together, because name resolution depends on having typ
 2335        // and type inference depends on having resolved names.
 2336        // The task is first performed for (the constraints of) newtype declarations, (the constraints of) subset type d
 2337        // (the right-hand sides of) const declarations, because type resolution sometimes needs to know the base type o
 2338        // and needs to know the type of const fields. Doing these declarations increases the chances the right informat
 2339        // in time.
 2340        // Once the task is done for these newtype/subset-type/const parts, the task continues with everything else.
 3262341        ResolveNamesAndInferTypes(declarations, true);
 3262342        ResolveNamesAndInferTypes(declarations, false);
 3262343      }
 2344
 2345      // Check that all types have been determined. During this process, also fill in all .ResolvedOp fields.
 6522346      if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 3262347        var checkTypeInferenceVisitor = new CheckTypeInferenceVisitor(this);
 3262348        checkTypeInferenceVisitor.VisitDeclarations(declarations);
 3262349      }
 2350
 2351      // Substitute for DefaultValueExpression's
 3262352      FillInDefaultValueExpressions();
 2353
 2354      // ---------------------------------- Pass 1 ----------------------------------
 2355      // This pass does the following:
 2356      // * desugar functions used in reads clauses
 2357      // * compute .BodySurrogate for body-less loops
 2358      // * discovers bounds
 2359      // * builds the module's call graph.
 2360      // * compute and checks ghosts (this makes use of bounds discovery, as done above)
 2361      // * for newtypes, figure out native types
 2362      // * for datatypes, check that shared destructors are in agreement in ghost matters
 2363      // * for functions and methods, determine tail recursion
 2364      // ----------------------------------------------------------------------------
 2365
 2366      // Discover bounds. These are needed later to determine if certain things are ghost or compiled,
 2367      // and thus this should be done before building the call graph.
 2368      // The BoundsDiscoveryVisitor also desugars FrameExpressions, so that bounds discovery can
 2369      // apply to the desugared versions.
 2370      // This pass also computes body surrogates for body-less loops, which is a bit like desugaring
 2371      // such loops.
 6422372      if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 3162373        var boundsDiscoveryVisitor = new BoundsDiscoveryVisitor(reporter);
 3162374        boundsDiscoveryVisitor.VisitDeclarations(declarations);
 3162375      }
 2376
 6422377      if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 3162378        CallGraphBuilder.Build(declarations, reporter);
 3162379      }
 2380
 2381      // Compute ghost interests, figure out native types, check agreement among datatype destructors, and determine tai
 6422382      if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 35762383        foreach (TopLevelDecl d in declarations) {
 8762384          if (d is IteratorDecl) {
 02385            var iter = (IteratorDecl)d;
 02386            iter.SubExpressions.Iter(e => CheckExpression(e, this, iter));
 02387            if (iter.Body != null) {
 02388              ComputeGhostInterest(iter.Body, false, null, iter);
 02389              CheckExpression(iter.Body, this, iter);
 02390            }
 2391
 11002392          } else if (d is SubsetTypeDecl subsetTypeDecl) {
 2242393            Contract.Assert(subsetTypeDecl.Constraint != null);
 2242394            CheckExpression(subsetTypeDecl.Constraint, this, new CodeContextWrapper(subsetTypeDecl, true));
 2242395            subsetTypeDecl.ConstraintIsCompilable =
 2242396              ExpressionTester.CheckIsCompilable(Options, null, subsetTypeDecl.Constraint, new CodeContextWrapper(subset
 2242397            subsetTypeDecl.CheckedIfConstraintIsCompilable = true;
 2398
 2242399            if (subsetTypeDecl.Witness != null) {
 02400              CheckExpression(subsetTypeDecl.Witness, this, new CodeContextWrapper(subsetTypeDecl, subsetTypeDecl.Witnes
 02401              if (subsetTypeDecl.WitnessKind == SubsetTypeDecl.WKind.Compiled) {
 02402                var codeContext = new CodeContextWrapper(subsetTypeDecl, subsetTypeDecl.WitnessKind == SubsetTypeDecl.WK
 02403                ExpressionTester.CheckIsCompilable(Options, this, subsetTypeDecl.Witness, codeContext);
 02404              }
 02405            }
 2406
 8762407          } else if (d is NewtypeDecl newtypeDecl) {
 02408            if (newtypeDecl.Var != null) {
 02409              Contract.Assert(newtypeDecl.Constraint != null);
 02410              CheckExpression(newtypeDecl.Constraint, this, new CodeContextWrapper(newtypeDecl, true));
 02411              if (newtypeDecl.Witness != null) {
 02412                CheckExpression(newtypeDecl.Witness, this, new CodeContextWrapper(newtypeDecl, newtypeDecl.WitnessKind =
 02413              }
 02414            }
 02415            if (newtypeDecl.Witness != null && newtypeDecl.WitnessKind == SubsetTypeDecl.WKind.Compiled) {
 02416              var codeContext = new CodeContextWrapper(newtypeDecl, newtypeDecl.WitnessKind == SubsetTypeDecl.WKind.Ghos
 02417              ExpressionTester.CheckIsCompilable(Options, this, newtypeDecl.Witness, codeContext);
 02418            }
 2419
 02420            FigureOutNativeType(newtypeDecl);
 2421
 8762422          } else if (d is DatatypeDecl) {
 2242423            var dd = (DatatypeDecl)d;
 37142424            foreach (var member in classMembers[dd].Values) {
 10142425              var dtor = member as DatatypeDestructor;
 15242426              if (dtor != null) {
 5102427                var rolemodel = dtor.CorrespondingFormals[0];
 10202428                for (int i = 1; i < dtor.CorrespondingFormals.Count; i++) {
 02429                  var other = dtor.CorrespondingFormals[i];
 02430                  if (rolemodel.IsGhost != other.IsGhost) {
 02431                    reporter.Error(MessageSource.Resolver, other,
 02432                      "shared destructors must agree on whether or not they are ghost, but '{0}' is {1} in constructor '
 02433                      rolemodel.Name,
 02434                      rolemodel.IsGhost ? "ghost" : "non-ghost", dtor.EnclosingCtors[0].Name,
 02435                      other.IsGhost ? "ghost" : "non-ghost", dtor.EnclosingCtors[i].Name);
 02436                  }
 02437                }
 5102438              }
 10142439            }
 21842440            foreach (var ctor in dd.Ctors) {
 5042441              CheckParameterDefaultValuesAreCompilable(ctor.Formals, dd);
 5042442            }
 2242443          }
 2444
 15282445          if (d is TopLevelDeclWithMembers cl) {
 6522446            ResolveClassMembers_Pass1(cl);
 6522447          }
 8762448        }
 3162449      }
 2450
 2451      // ---------------------------------- Pass 2 ----------------------------------
 2452      // This pass fills in various additional information.
 2453      // * Subset type in comprehensions have a compilable constraint
 2454      // * Postconditions and bodies of prefix lemmas
 2455      // * Compute postconditions and statement body of prefix lemmas
 2456      // * Perform the stratosphere check on inductive datatypes, and compute to what extent the inductive datatypes req
 2457      // * Set the SccRepr field of codatatypes
 2458      // * Perform the guardedness check on co-datatypes
 2459      // * Do datatypes and type synonyms until a fixpoint is reached, same for functions and methods
 2460      // * Check that functions claiming to be abstemious really are
 2461      // * Check that all == and != operators in non-ghost contexts are applied to equality-supporting types.
 2462      // * Extreme predicate recursivity checks
 2463      // * Verify that subset constraints are compilable if necessary
 2464      // ----------------------------------------------------------------------------
 2465
 6422466      if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 2467        // fill in the postconditions and bodies of prefix lemmas
 3162468        FillInPostConditionsAndBodiesOfPrefixLemmas(declarations);
 3162469      }
 2470
 2471      // Perform the stratosphere check on inductive datatypes, and compute to what extent the inductive datatypes requi
 17852472      foreach (var dtd in datatypeDependencies.TopologicallySortedComponents()) {
 5382473        if (datatypeDependencies.GetSCCRepresentative(dtd) == dtd) {
 2474          // do the following check once per SCC, so call it on each SCC representative
 2692475          SccStratosphereCheck(dtd, datatypeDependencies);
 2692476          DetermineEqualitySupport(dtd, datatypeDependencies);
 2692477        }
 2692478      }
 2479
 2480      // Set the SccRepr field of codatatypes
 9782481      foreach (var repr in codatatypeDependencies.TopologicallySortedComponents()) {
 02482        foreach (var codt in codatatypeDependencies.GetSCC(repr)) {
 02483          codt.SscRepr = repr;
 02484        }
 02485      }
 2486
 6422487      if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {  // because CheckCoCalls requires the given expression t
 2488        // Perform the guardedness check on co-datatypes
 9482489        foreach (var repr in ModuleDefinition.AllFunctionSCCs(declarations)) {
 02490          var module = repr.EnclosingModule;
 02491          bool dealsWithCodatatypes = false;
 02492          foreach (var m in module.CallGraph.GetSCC(repr)) {
 02493            var f = m as Function;
 02494            if (f != null && f.ResultType.InvolvesCoDatatype) {
 02495              dealsWithCodatatypes = true;
 02496              break;
 2497            }
 02498          }
 02499          var coCandidates = new List<CoCallResolution.CoCallInfo>();
 02500          var hasIntraClusterCallsInDestructiveContexts = false;
 02501          foreach (var m in module.CallGraph.GetSCC(repr)) {
 02502            var f = m as Function;
 02503            if (f != null && f.Body != null) {
 02504              var checker = new CoCallResolution(f, dealsWithCodatatypes);
 02505              checker.CheckCoCalls(f.Body);
 02506              coCandidates.AddRange(checker.FinalCandidates);
 02507              hasIntraClusterCallsInDestructiveContexts |= checker.HasIntraClusterCallsInDestructiveContexts;
 02508            } else if (f == null) {
 2509              // the SCC contains a method, which we always consider to be a destructive context
 02510              hasIntraClusterCallsInDestructiveContexts = true;
 02511            }
 02512          }
 02513          if (coCandidates.Count != 0) {
 02514            if (hasIntraClusterCallsInDestructiveContexts) {
 02515              foreach (var c in coCandidates) {
 02516                c.CandidateCall.CoCall = FunctionCallExpr.CoCallResolution.NoBecauseRecursiveCallsInDestructiveContext;
 02517              }
 02518            } else {
 02519              foreach (var c in coCandidates) {
 02520                c.CandidateCall.CoCall = FunctionCallExpr.CoCallResolution.Yes;
 02521                c.EnclosingCoConstructor.IsCoCall = true;
 02522                reporter.Info(MessageSource.Resolver, c.CandidateCall.tok, "co-recursive call");
 02523              }
 2524              // Finally, fill in the CoClusterTarget field
 2525              // Start by setting all the CoClusterTarget fields to CoRecursiveTargetAllTheWay.
 02526              foreach (var m in module.CallGraph.GetSCC(repr)) {
 02527                var f = (Function)m;  // the cast is justified on account of that we allow co-recursive calls only in cl
 02528                f.CoClusterTarget = Function.CoCallClusterInvolvement.CoRecursiveTargetAllTheWay;
 02529              }
 2530              // Then change the field to IsMutuallyRecursiveTarget whenever we see a non-self recursive non-co-recursiv
 02531              foreach (var m in module.CallGraph.GetSCC(repr)) {
 02532                var f = (Function)m;  // cast is justified just like above
 02533                foreach (var call in f.AllCalls) {
 02534                  if (call.CoCall != FunctionCallExpr.CoCallResolution.Yes && call.Function != f && ModuleDefinition.InS
 02535                    call.Function.CoClusterTarget = Function.CoCallClusterInvolvement.IsMutuallyRecursiveTarget;
 02536                  }
 02537                }
 02538              }
 02539            }
 02540          }
 02541        }
 2542        // Inferred required equality support for datatypes and type synonyms, and for Function and Method signatures.
 2543        // First, do datatypes and type synonyms until a fixpoint is reached.
 2544        bool inferredSomething;
 3162545        do {
 3162546          inferredSomething = false;
 35762547          foreach (var d in declarations) {
 8762548            if (Attributes.Contains(d.Attributes, "_provided")) {
 2549              // Don't infer required-equality-support for the type parameters, since there are
 2550              // scopes that see the name of the declaration but not its body.
 11002551            } else if (d is DatatypeDecl) {
 2242552              var dt = (DatatypeDecl)d;
 12962553              foreach (var tp in dt.TypeArgs) {
 4162554                if (tp.Characteristics.EqualitySupport == TypeParameter.EqualitySupportValue.Unspecified) {
 2555                  // here's our chance to infer the need for equality support
 20282556                  foreach (var ctor in dt.Ctors) {
 29342557                    foreach (var arg in ctor.Formals) {
 5102558                      if (InferRequiredEqualitySupport(tp, arg.Type)) {
 02559                        tp.Characteristics.EqualitySupport = TypeParameter.EqualitySupportValue.InferredRequired;
 02560                        inferredSomething = true;
 02561                        goto DONE_DT;  // break out of the doubly-nested loop
 2562                      }
 5102563                    }
 4682564                  }
 4162565                DONE_DT:;
 2082566                }
 2082567              }
 11002568            } else if (d is TypeSynonymDecl) {
 2242569              var syn = (TypeSynonymDecl)d;
 10082570              foreach (var tp in syn.TypeArgs) {
 2242571                if (tp.Characteristics.EqualitySupport == TypeParameter.EqualitySupportValue.Unspecified) {
 2572                  // here's our chance to infer the need for equality support
 1122573                  if (InferRequiredEqualitySupport(tp, syn.Rhs)) {
 02574                    tp.Characteristics.EqualitySupport = TypeParameter.EqualitySupportValue.InferredRequired;
 02575                    inferredSomething = true;
 02576                  }
 1122577                }
 1122578              }
 2242579            }
 8762580          }
 6322581        } while (inferredSomething);
 2582        // Now do it for Function and Method signatures.
 35762583        foreach (var d in declarations) {
 8762584          if (d is IteratorDecl) {
 02585            var iter = (IteratorDecl)d;
 02586            var done = false;
 02587            var nonnullIter = iter.NonNullTypeDecl;
 02588            Contract.Assert(nonnullIter.TypeArgs.Count == iter.TypeArgs.Count);
 02589            for (var i = 0; i < iter.TypeArgs.Count; i++) {
 02590              var tp = iter.TypeArgs[i];
 02591              var correspondingNonnullIterTypeParameter = nonnullIter.TypeArgs[i];
 02592              if (tp.Characteristics.EqualitySupport == TypeParameter.EqualitySupportValue.Unspecified) {
 2593                // here's our chance to infer the need for equality support
 02594                foreach (var p in iter.Ins) {
 02595                  if (InferRequiredEqualitySupport(tp, p.Type)) {
 02596                    tp.Characteristics.EqualitySupport = TypeParameter.EqualitySupportValue.InferredRequired;
 02597                    correspondingNonnullIterTypeParameter.Characteristics.EqualitySupport = TypeParameter.EqualitySuppor
 02598                    done = true;
 02599                    break;
 2600                  }
 02601                }
 02602                foreach (var p in iter.Outs) {
 02603                  if (done) {
 02604                    break;
 2605                  }
 2606
 02607                  if (InferRequiredEqualitySupport(tp, p.Type)) {
 02608                    tp.Characteristics.EqualitySupport = TypeParameter.EqualitySupportValue.InferredRequired;
 02609                    correspondingNonnullIterTypeParameter.Characteristics.EqualitySupport = TypeParameter.EqualitySuppor
 02610                    break;
 2611                  }
 02612                }
 02613              }
 02614            }
 13042615          } else if (d is ClassDecl) {
 4282616            var cl = (ClassDecl)d;
 72722617            foreach (var member in cl.Members) {
 39922618              if (!member.IsGhost) {
 19962619                if (member is Function) {
 02620                  var f = (Function)member;
 02621                  foreach (var tp in f.TypeArgs) {
 02622                    if (tp.Characteristics.EqualitySupport == TypeParameter.EqualitySupportValue.Unspecified) {
 2623                      // here's our chance to infer the need for equality support
 02624                      if (InferRequiredEqualitySupport(tp, f.ResultType)) {
 02625                        tp.Characteristics.EqualitySupport = TypeParameter.EqualitySupportValue.InferredRequired;
 02626                      } else {
 02627                        foreach (var p in f.Formals) {
 02628                          if (InferRequiredEqualitySupport(tp, p.Type)) {
 02629                            tp.Characteristics.EqualitySupport = TypeParameter.EqualitySupportValue.InferredRequired;
 02630                            break;
 2631                          }
 02632                        }
 02633                      }
 02634                    }
 02635                  }
 38802636                } else if (member is Method) {
 18842637                  var m = (Method)member;
 18842638                  bool done = false;
 68762639                  foreach (var tp in m.TypeArgs) {
 8162640                    if (tp.Characteristics.EqualitySupport == TypeParameter.EqualitySupportValue.Unspecified) {
 2641                      // here's our chance to infer the need for equality support
 42842642                      foreach (var p in m.Ins) {
 10202643                        if (InferRequiredEqualitySupport(tp, p.Type)) {
 02644                          tp.Characteristics.EqualitySupport = TypeParameter.EqualitySupportValue.InferredRequired;
 02645                          done = true;
 02646                          break;
 2647                        }
 10202648                      }
 30602649                      foreach (var p in m.Outs) {
 6122650                        if (done) {
 02651                          break;
 2652                        }
 2653
 6122654                        if (InferRequiredEqualitySupport(tp, p.Type)) {
 02655                          tp.Characteristics.EqualitySupport = TypeParameter.EqualitySupportValue.InferredRequired;
 02656                          break;
 2657                        }
 6122658                      }
 4082659                    }
 4082660                  }
 18842661                }
 19962662              }
 19962663            }
 4282664          }
 8762665        }
 2666        // Check that functions claiming to be abstemious really are, and check that 'older' parameters are used only wh
 9482667        foreach (var fn in ModuleDefinition.AllFunctions(declarations)) {
 02668          new Abstemious(reporter).Check(fn);
 02669          CheckOlderParameters(fn);
 02670        }
 2671        // Check that all == and != operators in non-ghost contexts are applied to equality-supporting types.
 2672        // Note that this check can only be done after determining which expressions are ghosts.
 35762673        foreach (var d in declarations) {
 30962674          for (var attr = d.Attributes; attr != null; attr = attr.Prev) {
 6722675            attr.Args.Iter(e => CheckTypeCharacteristics_Expr(e, true));
 4482676          }
 2677
 8762678          if (d is IteratorDecl) {
 02679            var iter = (IteratorDecl)d;
 02680            foreach (var p in iter.Ins) {
 02681              CheckTypeCharacteristics_Type(p.tok, p.Type, p.IsGhost);
 02682            }
 02683            foreach (var p in iter.Outs) {
 02684              CheckTypeCharacteristics_Type(p.tok, p.Type, p.IsGhost);
 02685            }
 02686            if (iter.Body != null) {
 02687              CheckTypeCharacteristics_Stmt(iter.Body, false);
 02688            }
 13042689          } else if (d is ClassDecl) {
 4282690            var cl = (ClassDecl)d;
 12842691            foreach (var parentTrait in cl.ParentTraits) {
 02692              CheckTypeCharacteristics_Type(cl.tok, parentTrait, false);
 02693            }
 11002694          } else if (d is DatatypeDecl) {
 2242695            var dt = (DatatypeDecl)d;
 21842696            foreach (var ctor in dt.Ctors) {
 30422697              foreach (var p in ctor.Formals) {
 5102698                CheckTypeCharacteristics_Type(p.tok, p.Type, p.IsGhost);
 5102699              }
 5042700            }
 6722701          } else if (d is TypeSynonymDecl) {
 2242702            var syn = (TypeSynonymDecl)d;
 2242703            CheckTypeCharacteristics_Type(syn.tok, syn.Rhs, false);
 4482704            if (!isAnExport) {
 2242705              if (syn.SupportsEquality && !syn.Rhs.SupportsEquality) {
 02706                reporter.Error(MessageSource.Resolver, syn.tok, "type '{0}' declared as supporting equality, but the RHS
 02707                  syn.Name, syn.Rhs);
 02708              }
 2242709              if (syn.Characteristics.IsNonempty && !syn.Rhs.IsNonempty) {
 02710                reporter.Error(MessageSource.Resolver, syn.tok, "type '{0}' declared as being nonempty, but the RHS type
 02711                  syn.Name, syn.Rhs);
 2242712              } else if (syn.Characteristics.HasCompiledValue && !syn.Rhs.HasCompilableValue) {
 02713                reporter.Error(MessageSource.Resolver, syn.tok,
 02714                  "type '{0}' declared as auto-initialization type, but the RHS type ({1}) does not support auto-initial
 02715              }
 2242716              if (syn.Characteristics.ContainsNoReferenceTypes && syn.Rhs.MayInvolveReferences) {
 02717                reporter.Error(MessageSource.Resolver, syn.tok,
 02718                  "type '{0}' declared as containing no reference types, but the RHS type ({1}) may contain reference ty
 02719              }
 2242720            }
 2242721          }
 2722
 11002723          if (d is RedirectingTypeDecl) {
 2242724            var rtd = (RedirectingTypeDecl)d;
 4482725            if (rtd.Constraint != null) {
 2242726              CheckTypeCharacteristics_Expr(rtd.Constraint, true);
 2242727            }
 2242728            if (rtd.Witness != null) {
 02729              CheckTypeCharacteristics_Expr(rtd.Witness, rtd.WitnessKind == SubsetTypeDecl.WKind.Ghost);
 02730            }
 2242731          }
 2732
 15282733          if (d is TopLevelDeclWithMembers) {
 6522734            var cl = (TopLevelDeclWithMembers)d;
 79442735            foreach (var member in cl.Members) {
 21082736              if (member is Field) {
 1122737                var f = (Field)member;
 1122738                CheckTypeCharacteristics_Type(f.tok, f.Type, f.IsGhost);
 1122739                if (f is ConstantField cf && cf.Rhs != null) {
 02740                  CheckTypeCharacteristics_Expr(cf.Rhs, cf.IsGhost);
 02741                }
 19962742              } else if (member is Function) {
 02743                var f = (Function)member;
 02744                foreach (var p in f.Formals) {
 02745                  CheckTypeCharacteristics_Type(p.tok, p.Type, f.IsGhost || p.IsGhost);
 02746                }
 02747                if (f.Body != null) {
 02748                  CheckTypeCharacteristics_Expr(f.Body, f.IsGhost);
 02749                }
 37682750              } else if (member is Method) {
 18842751                var m = (Method)member;
 171782752                foreach (var p in m.Ins) {
 38422753                  CheckTypeCharacteristics_Type(p.tok, p.Type, m.IsGhost || p.IsGhost);
 38422754                }
 123662755                foreach (var p in m.Outs) {
 22382756                  CheckTypeCharacteristics_Type(p.tok, p.Type, m.IsGhost || p.IsGhost);
 22382757                }
 37682758                if (m.Body != null) {
 18842759                  CheckTypeCharacteristics_Stmt(m.Body, m.IsGhost);
 18842760                }
 18842761              }
 19962762            }
 6522763          }
 8762764        }
 2765        // Check that extreme predicates are not recursive with non-extreme-predicate functions (and only
 2766        // with extreme predicates of the same polarity), and
 2767        // check that greatest lemmas are not recursive with non-greatest-lemma methods.
 2768        // Also, check that the constraints of newtypes/subset-types do not depend on the type itself.
 2769        // And check that const initializers are not cyclic.
 3162770        var cycleErrorHasBeenReported = new HashSet<ICallable>();
 35762771        foreach (var d in declarations) {
 15282772          if (d is TopLevelDeclWithMembers { Members: var members }) {
 79442773            foreach (var member in members) {
 19962774              if (member is ExtremePredicate) {
 02775                var fn = (ExtremePredicate)member;
 2776                // Check here for the presence of any 'ensures' clauses, which are not allowed (because we're not sure
 2777                // of their soundness)
 02778                fn.Req.ForEach(e => ExtremePredicateChecks(e.E, fn, CallingPosition.Positive));
 02779                fn.Decreases.Expressions.ForEach(e => ExtremePredicateChecks(e, fn, CallingPosition.Positive));
 02780                fn.Reads.ForEach(e => ExtremePredicateChecks(e.E, fn, CallingPosition.Positive));
 02781                if (fn.Ens.Count != 0) {
 02782                  reporter.Error(MessageSource.Resolver, fn.Ens[0].E.tok, "a {0} is not allowed to declare any ensures c
 02783                }
 02784                if (fn.Body != null) {
 02785                  ExtremePredicateChecks(fn.Body, fn, CallingPosition.Positive);
 02786                }
 19962787              } else if (member is ExtremeLemma) {
 02788                var m = (ExtremeLemma)member;
 02789                m.Req.ForEach(e => ExtremeLemmaChecks(e.E, m));
 02790                m.Ens.ForEach(e => ExtremeLemmaChecks(e.E, m));
 02791                m.Decreases.Expressions.ForEach(e => ExtremeLemmaChecks(e, m));
 2792
 02793                if (m.Body != null) {
 02794                  ExtremeLemmaChecks(m.Body, m);
 02795                }
 19962796              } else if (member is ConstantField) {
 02797                var cf = (ConstantField)member;
 02798                if (cf.EnclosingModule.CallGraph.GetSCCSize(cf) != 1) {
 02799                  var r = cf.EnclosingModule.CallGraph.GetSCCRepresentative(cf);
 02800                  if (cycleErrorHasBeenReported.Contains(r)) {
 2801                    // An error has already been reported for this cycle, so don't report another.
 2802                    // Note, the representative, "r", may itself not be a const.
 02803                  } else {
 02804                    ReportCallGraphCycleError(cf, "const definition contains a cycle");
 02805                    cycleErrorHasBeenReported.Add(r);
 02806                  }
 02807                }
 02808              }
 19962809            }
 6522810          }
 2811
 11002812          if (d is RedirectingTypeDecl dd) {
 2242813            if (d.EnclosingModuleDefinition.CallGraph.GetSCCSize(dd) != 1) {
 02814              var r = d.EnclosingModuleDefinition.CallGraph.GetSCCRepresentative(dd);
 02815              if (cycleErrorHasBeenReported.Contains(r)) {
 2816                // An error has already been reported for this cycle, so don't report another.
 2817                // Note, the representative, "r", may itself not be a const.
 02818              } else if (dd is NewtypeDecl || dd is SubsetTypeDecl) {
 02819                ReportCallGraphCycleError(dd, $"recursive constraint dependency involving a {dd.WhatKind}");
 02820                cycleErrorHasBeenReported.Add(r);
 02821              }
 02822            }
 2242823          }
 8762824        }
 3162825      }
 2826
 2827      // ---------------------------------- Pass 3 ----------------------------------
 2828      // Further checks
 2829      // ----------------------------------------------------------------------------
 2830
 6422831      if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 2832        // Check that type-parameter variance is respected in type definitions
 35762833        foreach (TopLevelDecl d in declarations) {
 13042834          if (d is IteratorDecl || d is ClassDecl) {
 16202835            foreach (var tp in d.TypeArgs) {
 1122836              if (tp.Variance != TypeParameter.TPVariance.Non) {
 02837                reporter.Error(MessageSource.Resolver, tp.tok, "{0} declarations only support non-variant type parameter
 02838              }
 1122839            }
 11002840          } else if (d is TypeSynonymDecl) {
 2242841            var dd = (TypeSynonymDecl)d;
 2242842            CheckVariance(dd.Rhs, dd, TypeParameter.TPVariance.Co, false);
 4482843          } else if (d is NewtypeDecl) {
 02844            var dd = (NewtypeDecl)d;
 02845            CheckVariance(dd.BaseType, dd, TypeParameter.TPVariance.Co, false);
 4482846          } else if (d is DatatypeDecl) {
 2242847            var dd = (DatatypeDecl)d;
 21842848            foreach (var ctor in dd.Ctors) {
 10142849              ctor.Formals.Iter(formal => CheckVariance(formal.Type, dd, TypeParameter.TPVariance.Co, false));
 5042850            }
 2242851          }
 8762852        }
 3162853      }
 2854
 6422855      if (reporter.Count(ErrorLevel.Error) == prevErrorCount) {
 2856        // Check that usage of "this" is restricted before "new;" in constructor bodies,
 2857        // and that a class without any constructor only has fields with known initializers.
 2858        // Also check that static fields (which are necessarily const) have initializers.
 3162859        var cdci = new CheckDividedConstructorInit_Visitor(this);
 29042860        foreach (var cl in ModuleDefinition.AllTypesWithMembers(declarations)) {
 8762861          if (!(cl is ClassDecl)) {
 4482862            if (!isAnExport && !cl.EnclosingModuleDefinition.IsAbstract) {
 2863              // non-reference types (datatype, newtype, opaque) don't have constructors that can initialize fields
 6722864              foreach (var member in cl.Members) {
 02865                if (member is ConstantField f && f.Rhs == null && !f.IsExtern(Options, out _, out _)) {
 02866                  CheckIsOkayWithoutRHS(f);
 02867                }
 02868              }
 2242869            }
 2242870            continue;
 2871          }
 5402872          if (cl is TraitDecl) {
 2242873            if (!isAnExport && !cl.EnclosingModuleDefinition.IsAbstract) {
 2874              // traits never have constructors, but check for static consts
 3362875              foreach (var member in cl.Members) {
 02876                if (member is ConstantField f && f.IsStatic && f.Rhs == null && !f.IsExtern(Options, out _, out _)) {
 02877                  CheckIsOkayWithoutRHS(f);
 02878                }
 02879              }
 1122880            }
 1122881            continue;
 2882          }
 3162883          var hasConstructor = false;
 3162884          Field fieldWithoutKnownInitializer = null;
 69362885          foreach (var member in cl.Members) {
 19962886            if (member is Constructor) {
 02887              hasConstructor = true;
 02888              var constructor = (Constructor)member;
 02889              if (constructor.BodyInit != null) {
 02890                cdci.CheckInit(constructor.BodyInit);
 02891              }
 19962892            } else if (member is ConstantField && member.IsStatic) {
 02893              var f = (ConstantField)member;
 02894              if (!isAnExport && !cl.EnclosingModuleDefinition.IsAbstract && f.Rhs == null && !f.IsExtern(Options, out _
 02895                CheckIsOkayWithoutRHS(f);
 02896              }
 21082897            } else if (member is Field && fieldWithoutKnownInitializer == null) {
 1122898              var f = (Field)member;
 1122899              if (f is ConstantField && ((ConstantField)f).Rhs != null) {
 2900                // fine
 1122901              } else if (!f.Type.KnownToHaveToAValue(f.IsGhost)) {
 02902                fieldWithoutKnownInitializer = f;
 02903              }
 1122904            }
 19962905          }
 6322906          if (!hasConstructor) {
 6322907            if (fieldWithoutKnownInitializer == null) {
 2908              // time to check inherited members
 9482909              foreach (var member in cl.InheritedMembers) {
 02910                if (member is Field) {
 02911                  var f = (Field)member;
 02912                  if (f is ConstantField && ((ConstantField)f).Rhs != null) {
 2913                    // fine
 02914                  } else if (!f.Type.Subst(cl.ParentFormalTypeParametersToActuals).KnownToHaveToAValue(f.IsGhost)) {
 02915                    fieldWithoutKnownInitializer = f;
 02916                    break;
 2917                  }
 02918                }
 02919              }
 3162920            }
 2921            // go through inherited members...
 3162922            if (fieldWithoutKnownInitializer != null) {
 02923              reporter.Error(MessageSource.Resolver, cl.tok, "class '{0}' with fields without known initializers, like '
 02924                cl.Name, fieldWithoutKnownInitializer.Name, fieldWithoutKnownInitializer.Type.Subst(cl.ParentFormalTypeP
 02925            }
 3162926          }
 3162927        }
 3162928      }
 2929      // Verifies that, in all compiled places, subset types in comprehensions have a compilable constraint
 3262930      new SubsetConstraintGhostChecker(this.Reporter).Traverse(declarations);
 3262931    }
 2932
 3162933    private void FillInPostConditionsAndBodiesOfPrefixLemmas(List<TopLevelDecl> declarations) {
 9482934      foreach (var com in ModuleDefinition.AllExtremeLemmas(declarations)) {
 02935        var prefixLemma = com.PrefixLemma;
 02936        if (prefixLemma == null) {
 02937          continue; // something went wrong during registration of the prefix lemma (probably a duplicated extreme lemma
 2938        }
 2939
 02940        var k = prefixLemma.Ins[0];
 02941        var focalPredicates = new HashSet<ExtremePredicate>();
 02942        if (com is GreatestLemma) {
 2943          // compute the postconditions of the prefix lemma
 02944          Contract.Assume(prefixLemma.Ens.Count == 0); // these are not supposed to have been filled in before
 02945          foreach (var p in com.Ens) {
 02946            var coConclusions = new HashSet<Expression>();
 02947            CollectFriendlyCallsInExtremeLemmaSpecification(p.E, true, coConclusions, true, com);
 02948            var subst = new ExtremeLemmaSpecificationSubstituter(coConclusions, new IdentifierExpr(k.tok, k.Name),
 02949              this.reporter, true);
 02950            var post = subst.CloneExpr(p.E);
 02951            prefixLemma.Ens.Add(new AttributedExpression(post));
 02952            foreach (var e in coConclusions) {
 02953              var fce = e as FunctionCallExpr;
 02954              if (fce != null) {
 2955                // the other possibility is that "e" is a BinaryExpr
 02956                GreatestPredicate predicate = (GreatestPredicate)fce.Function;
 02957                focalPredicates.Add(predicate);
 2958                // For every focal predicate P in S, add to S all greatest predicates in the same strongly connected
 2959                // component (in the call graph) as P
 02960                foreach (var node in predicate.EnclosingClass.EnclosingModuleDefinition.CallGraph.GetSCC(
 02961                           predicate)) {
 02962                  if (node is GreatestPredicate) {
 02963                    focalPredicates.Add((GreatestPredicate)node);
 02964                  }
 02965                }
 02966              }
 02967            }
 02968          }
 02969        } else {
 2970          // compute the preconditions of the prefix lemma
 02971          Contract.Assume(prefixLemma.Req.Count == 0); // these are not supposed to have been filled in before
 02972          foreach (var p in com.Req) {
 02973            var antecedents = new HashSet<Expression>();
 02974            CollectFriendlyCallsInExtremeLemmaSpecification(p.E, true, antecedents, false, com);
 02975            var subst = new ExtremeLemmaSpecificationSubstituter(antecedents, new IdentifierExpr(k.tok, k.Name),
 02976              this.reporter, false);
 02977            var pre = subst.CloneExpr(p.E);
 02978            prefixLemma.Req.Add(new AttributedExpression(pre, p.Label, null));
 02979            foreach (var e in antecedents) {
 02980              var fce = (FunctionCallExpr)e; // we expect "antecedents" to contain only FunctionCallExpr's
 02981              LeastPredicate predicate = (LeastPredicate)fce.Function;
 02982              focalPredicates.Add(predicate);
 2983              // For every focal predicate P in S, add to S all least predicates in the same strongly connected
 2984              // component (in the call graph) as P
 02985              foreach (var node in predicate.EnclosingClass.EnclosingModuleDefinition.CallGraph.GetSCC(predicate)) {
 02986                if (node is LeastPredicate) {
 02987                  focalPredicates.Add((LeastPredicate)node);
 02988                }
 02989              }
 02990            }
 02991          }
 02992        }
 2993
 02994        reporter.Info(MessageSource.Resolver, com.tok,
 02995          focalPredicates.Count == 0
 02996            ? $"{com.PrefixLemma.Name} has no focal predicates"
 02997            : $"{com.PrefixLemma.Name} with focal predicate{Util.Plural(focalPredicates.Count)} {Util.Comma(focalPredica
 2998        // Compute the statement body of the prefix lemma
 02999        Contract.Assume(prefixLemma.Body == null); // this is not supposed to have been filled in before
 03000        if (com.Body != null) {
 03001          var kMinusOne = new BinaryExpr(com.tok, BinaryExpr.Opcode.Sub, new IdentifierExpr(k.tok, k.Name),
 03002            new LiteralExpr(com.tok, 1));
 03003          var subst = new ExtremeLemmaBodyCloner(com, kMinusOne, focalPredicates, this.reporter);
 03004          var mainBody = subst.CloneBlockStmt(com.Body);
 3005          Expression kk;
 3006          Statement els;
 03007          if (k.Type.IsBigOrdinalType) {
 03008            kk = new MemberSelectExpr(k.tok, new IdentifierExpr(k.tok, k.Name), "Offset");
 3009            // As an "else" branch, we add recursive calls for the limit case.  When automatic induction is on,
 3010            // this get handled automatically, but we still want it in the case when automatic induction has been
 3011            // turned off.
 3012            //     forall k', params | k' < _k && Precondition {
 3013            //       pp(k', params);
 3014            //     }
 03015            Contract.Assume(builtIns.ORDINAL_Offset != null); // should have been filled in earlier
 03016            var kId = new IdentifierExpr(com.tok, k);
 03017            var kprimeVar = new BoundVar(com.tok, "_k'", Type.BigOrdinal);
 03018            var kprime = new IdentifierExpr(com.tok, kprimeVar);
 03019            var smaller = Expression.CreateLess(kprime, kId);
 3020
 03021            var bvs = new List<BoundVar>(); // the following loop populates bvs with k', params
 03022            var substMap = new Dictionary<IVariable, Expression>();
 03023            foreach (var inFormal in prefixLemma.Ins) {
 03024              if (inFormal == k) {
 03025                bvs.Add(kprimeVar);
 03026                substMap.Add(k, kprime);
 03027              } else {
 03028                var bv = new BoundVar(inFormal.tok, inFormal.Name, inFormal.Type);
 03029                bvs.Add(bv);
 03030                substMap.Add(inFormal, new IdentifierExpr(com.tok, bv));
 03031              }
 03032            }
 3033
 03034            Translator.RecursiveCallParameters(com.tok, prefixLemma, prefixLemma.TypeArgs, prefixLemma.Ins, null,
 03035              substMap, out var recursiveCallReceiver, out var recursiveCallArgs);
 03036            var methodSel = new MemberSelectExpr(com.tok, recursiveCallReceiver, prefixLemma.Name);
 03037            methodSel.Member = prefixLemma; // resolve here
 03038            methodSel.TypeApplication_AtEnclosingClass =
 03039              prefixLemma.EnclosingClass.TypeArgs.ConvertAll(tp => (Type)new UserDefinedType(tp.tok, tp));
 03040            methodSel.TypeApplication_JustMember =
 03041              prefixLemma.TypeArgs.ConvertAll(tp => (Type)new UserDefinedType(tp.tok, tp));
 03042            methodSel.Type = new InferredTypeProxy();
 03043            var recursiveCall = new CallStmt(com.RangeToken, new List<Expression>(), methodSel,
 03044              recursiveCallArgs.ConvertAll(e => new ActualBinding(null, e)));
 03045            recursiveCall.IsGhost = prefixLemma.IsGhost; // resolve here
 3046
 03047            var range = smaller; // The range will be strengthened later with the call's precondition, substituted
 3048            // appropriately (which can only be done once the precondition has been resolved).
 03049            var attrs = new Attributes("_autorequires", new List<Expression>(), null);
 3050#if VERIFY_CORRECTNESS_OF_TRANSLATION_FORALL_STATEMENT_RANGE
 3051              // don't add the :_trustWellformed attribute
 3052#else
 03053            attrs = new Attributes("_trustWellformed", new List<Expression>(), attrs);
 3054#endif
 03055            attrs = new Attributes("auto_generated", new List<Expression>(), attrs);
 03056            var forallBody = new BlockStmt(mainBody.RangeToken, new List<Statement>() { recursiveCall });
 03057            var forallStmt = new ForallStmt(mainBody.RangeToken, bvs, attrs, range,
 03058              new List<AttributedExpression>(), forallBody);
 03059            els = new BlockStmt(mainBody.RangeToken, new List<Statement>() { forallStmt });
 03060          } else {
 03061            kk = new IdentifierExpr(k.tok, k.Name);
 03062            els = null;
 03063          }
 3064
 03065          var kPositive = new BinaryExpr(com.tok, BinaryExpr.Opcode.Lt, new LiteralExpr(com.tok, 0), kk);
 03066          var condBody = new IfStmt(mainBody.RangeToken, false, kPositive, mainBody, els);
 03067          prefixLemma.Body = new BlockStmt(mainBody.RangeToken, new List<Statement>() { condBody });
 03068        }
 3069
 3070        // The prefix lemma now has all its components, so it's finally time we resolve it
 03071        currentClass = (TopLevelDeclWithMembers)prefixLemma.EnclosingClass;
 03072        allTypeParameters.PushMarker();
 03073        ResolveTypeParameters(currentClass.TypeArgs, false, currentClass);
 03074        ResolveTypeParameters(prefixLemma.TypeArgs, false, prefixLemma);
 03075        prefixLemma.Resolve(this);
 03076        allTypeParameters.PopMarker();
 03077        currentClass = null;
 03078        new CheckTypeInferenceVisitor(this).VisitMethod(prefixLemma);
 03079        CallGraphBuilder.VisitMethod(prefixLemma, reporter);
 03080        new BoundsDiscoveryVisitor(reporter).VisitMethod(prefixLemma);
 03081      }
 3163082    }
 3083
 03084    private void CheckIsOkayWithoutRHS(ConstantField f) {
 03085      if (f.IsGhost && !f.Type.IsNonempty) {
 03086        reporter.Error(MessageSource.Resolver, f.tok,
 03087          "{0}ghost const field '{1}' of type '{2}' (which may be empty) must give a defining value",
 03088          f.IsStatic ? "static " : "", f.Name, f.Type);
 03089      } else if (!f.IsGhost && !f.Type.HasCompilableValue) {
 03090        reporter.Error(MessageSource.Resolver, f.tok,
 03091          "{0}non-ghost const field '{1}' of type '{2}' (which does not have a default compiled value) must give a defin
 03092          f.IsStatic ? "static " : "", f.Name, f.Type);
 03093      }
 03094    }
 3095
 6523096    private void ResolveClassMembers_Pass1(TopLevelDeclWithMembers cl) {
 79443097      foreach (var member in cl.Members) {
 19963098        var prevErrCnt = reporter.Count(ErrorLevel.Error);
 39923099        if (prevErrCnt == reporter.Count(ErrorLevel.Error)) {
 38803100          if (member is Method method) {
 18843101            CheckForUnnecessaryEqualitySupportDeclarations(method, method.TypeArgs);
 18843102            CheckParameterDefaultValuesAreCompilable(method.Ins, method);
 37683103            if (method.Body != null) {
 18843104              ComputeGhostInterest(method.Body, method.IsGhost, method.IsLemmaLike ? "a " + method.WhatKind : null, meth
 18843105              CheckExpression(method.Body, this, method);
 18843106              new TailRecursion(reporter).DetermineTailRecursion(method);
 18843107            }
 3108
 19963109          } else if (member is Function function) {
 03110            CheckForUnnecessaryEqualitySupportDeclarations(function, function.TypeArgs);
 03111            CheckParameterDefaultValuesAreCompilable(function.Formals, function);
 03112            if (function.ByMethodBody == null) {
 03113              if (!function.IsGhost && function.Body != null) {
 03114                ExpressionTester.CheckIsCompilable(Options, this, function.Body, function);
 03115              }
 03116              if (function.Body != null) {
 03117                new TailRecursion(reporter).DetermineTailRecursion(function);
 03118              }
 03119            } else {
 03120              var m = function.ByMethodDecl;
 03121              if (m != null) {
 03122                Contract.Assert(!m.IsGhost);
 03123                ComputeGhostInterest(m.Body, false, null, m);
 03124                CheckExpression(m.Body, this, m);
 03125                new TailRecursion(reporter).DetermineTailRecursion(m);
 03126              } else {
 3127                // m should not be null, unless an error has been reported
 3128                // (e.g. function-by-method and method with the same name)
 03129                Contract.Assert(reporter.ErrorCount > 0);
 03130              }
 03131            }
 3132
 1123133          } else if (member is ConstantField field && field.Rhs != null && !field.IsGhost) {
 03134            ExpressionTester.CheckIsCompilable(Options, this, field.Rhs, field);
 03135          }
 3136
 38803137          if (prevErrCnt == reporter.Count(ErrorLevel.Error) && member is ICodeContext) {
 38443138            member.SubExpressions.Iter(e => CheckExpression(e, this, (ICodeContext)member));
 18843139          }
 19963140        }
 19963141      }
 6523142    }
 3143
 18843144    void CheckForUnnecessaryEqualitySupportDeclarations(MemberDecl member, List<TypeParameter> typeParameters) {
 18843145      if (member.IsGhost) {
 03146        foreach (var p in typeParameters.Where(p => p.SupportsEquality)) {
 03147          reporter.Warning(MessageSource.Resolver, ErrorRegistry.NoneId, p.tok,
 03148            $"type parameter {p.Name} of ghost {member.WhatKind} {member.Name} is declared (==), which is unnecessary be
 03149        }
 03150      }
 18843151    }
 3152
 3153    /// <summary>
 3154    /// Check that default-value expressions are compilable, for non-ghost formals.
 3155    /// </summary>
 23883156    void CheckParameterDefaultValuesAreCompilable(List<Formal> formals, ICodeContext codeContext) {
 3157      Contract.Requires(formals != null);
 3158
 115163159      foreach (var formal in formals.Where(f => f.DefaultValue != null)) {
 03160        if ((!codeContext.IsGhost || codeContext is DatatypeDecl) && !formal.IsGhost) {
 03161          ExpressionTester.CheckIsCompilable(Options, this, formal.DefaultValue, codeContext);
 03162        }
 03163        CheckExpression(formal.DefaultValue, this, codeContext);
 03164      }
 23883165    }
 3166
 03167    void ReportCallGraphCycleError(ICallable start, string msg) {
 3168      Contract.Requires(start != null);
 3169      Contract.Requires(msg != null);
 03170      var scc = start.EnclosingModule.CallGraph.GetSCC(start);
 03171      scc.Reverse();
 03172      var startIndex = scc.IndexOf(start);
 03173      Contract.Assert(0 <= startIndex);
 03174      scc = Util.Concat(scc.GetRange(startIndex, scc.Count - startIndex), scc.GetRange(0, startIndex));
 03175      ReportCycleError(scc, c => c.Tok, c => c.NameRelativeToModule, msg);
 03176    }
 3177
 03178    void ReportCycleError<X>(List<X> cycle, Func<X, IToken> toTok, Func<X, string> toString, string msg) {
 3179      Contract.Requires(cycle != null);
 3180      Contract.Requires(cycle.Count != 0);
 3181      Contract.Requires(toTok != null);
 3182      Contract.Requires(toString != null);
 3183      Contract.Requires(msg != null);
 3184
 03185      var start = cycle[0];
 03186      var cy = Util.Comma(" -> ", cycle, toString);
 03187      reporter.Error(MessageSource.Resolver, toTok(start), $"{msg}: {cy} -> {toString(start)}");
 03188    }
 3189
 3190    /// <summary>
 3191    /// Returns the largest value that can be stored in bitvector type "t".
 3192    /// </summary>
 03193    public static BigInteger MaxBV(Type t) {
 3194      Contract.Requires(t != null);
 3195      Contract.Requires(t.IsBitVectorType);
 03196      return MaxBV(t.AsBitVectorType.Width);
 03197    }
 3198
 3199    /// <summary>
 3200    /// Returns the largest value that can be stored in bitvector type of "bits" width.
 3201    /// </summary>
 03202    public static BigInteger MaxBV(int bits) {
 3203      Contract.Requires(0 <= bits);
 03204      return BigInteger.Pow(new BigInteger(2), bits) - BigInteger.One;
 03205    }
 3206
 03207    private void FigureOutNativeType(NewtypeDecl dd) {
 3208      Contract.Requires(dd != null);
 3209
 3210      // Look at the :nativeType attribute, if any
 3211      bool mustUseNativeType;
 03212      List<NativeType> nativeTypeChoices = null;  // null means "no preference"
 03213      var args = Attributes.FindExpressions(dd.Attributes, "nativeType");
 03214      if (args != null && !dd.BaseType.IsNumericBased(Type.NumericPersuasion.Int)) {
 03215        reporter.Error(MessageSource.Resolver, dd, ":nativeType can only be used on integral types");
 03216        return;
 03217      } else if (args == null) {
 3218        // There was no :nativeType attribute
 03219        mustUseNativeType = false;
 03220      } else if (args.Count == 0) {
 03221        mustUseNativeType = true;
 03222      } else {
 03223        var arg0Lit = args[0] as LiteralExpr;
 03224        if (arg0Lit != null && arg0Lit.Value is bool) {
 03225          if (!(bool)arg0Lit.Value) {
 3226            // {:nativeType false} says "don't use native type", so our work here is done
 03227            return;
 3228          }
 03229          mustUseNativeType = true;
 03230        } else {
 03231          mustUseNativeType = true;
 03232          nativeTypeChoices = new List<NativeType>();
 03233          foreach (var arg in args) {
 03234            if (arg is LiteralExpr lit && lit.Value is string s) {
 3235              // Get the NativeType for "s"
 03236              foreach (var nativeT in NativeTypes) {
 03237                if (nativeT.Name == s) {
 03238                  nativeTypeChoices.Add(nativeT);
 03239                  goto FoundNativeType;
 3240                }
 03241              }
 03242              reporter.Error(MessageSource.Resolver, dd, ":nativeType '{0}' not known", s);
 03243              return;
 03244            FoundNativeType:;
 03245            } else {
 03246              reporter.Error(MessageSource.Resolver, arg, "unexpected :nativeType argument");
 03247              return;
 3248            }
 03249          }
 03250        }
 03251      }
 3252
 3253      // Figure out the variable and constraint.  Usually, these would be just .Var and .Constraint, but
 3254      // in the case .Var is null, these can be computed from the .BaseType recursively.
 03255      var ddVar = dd.Var;
 03256      var ddConstraint = dd.Constraint;
 03257      for (var ddWhereConstraintsAre = dd; ddVar == null;) {
 03258        ddWhereConstraintsAre = ddWhereConstraintsAre.BaseType.AsNewtype;
 03259        if (ddWhereConstraintsAre == null) {
 03260          break;
 3261        }
 03262        ddVar = ddWhereConstraintsAre.Var;
 03263        ddConstraint = ddWhereConstraintsAre.Constraint;
 03264      }
 3265      List<ComprehensionExpr.BoundedPool> bounds;
 03266      if (ddVar == null) {
 3267        // There are no bounds at all
 03268        bounds = new List<ComprehensionExpr.BoundedPool>();
 03269      } else {
 03270        bounds = DiscoverAllBounds_SingleVar(ddVar, ddConstraint);
 03271      }
 3272
 3273      // Returns null if the argument is a constrained newtype (recursively)
 3274      // Returns the transitive base type if the argument is recusively unconstrained
 03275      Type AsUnconstrainedType(Type t) {
 03276        while (true) {
 03277          if (t.AsNewtype == null) {
 03278            return t;
 3279          }
 3280
 03281          if (t.AsNewtype.Constraint != null) {
 03282            return null;
 3283          }
 3284
 03285          t = t.AsNewtype.BaseType;
 03286        }
 03287      }
 3288
 3289      // Find which among the allowable native types can hold "dd". Give an
 3290      // error for any user-specified native type that's not big enough.
 03291      var bigEnoughNativeTypes = new List<NativeType>();
 3292      // But first, define a local, recursive function GetConst/GetAnyConst:
 3293      // These fold any constant computations, including symbolic constants,
 3294      // returning null if folding is not possible. If an operation is undefined
 3295      // (divide by zero, conversion out of range, etc.), then null is returned.
 03296      Func<Expression, BigInteger?> GetConst = null;
 03297      Func<Expression, Stack<ConstantField>, Object> GetAnyConst = null;
 03298      GetAnyConst = (Expression e, Stack<ConstantField> consts) => {
 03299        if (e is LiteralExpr l) {
 03300          return l.Value;
 03301        } else if (e is UnaryOpExpr un) {
 03302          if (un.ResolvedOp == UnaryOpExpr.ResolvedOpcode.BoolNot && GetAnyConst(un.E, consts) is bool b) {
 03303            return !b;
 03304          }
 03305          if (un.ResolvedOp == UnaryOpExpr.ResolvedOpcode.BVNot && GetAnyConst(un.E, consts) is BigInteger i) {
 03306            return ((BigInteger.One << un.Type.AsBitVectorType.Width) - 1) ^ i;
 03307          }
 03308          // TODO: This only handles strings; generalize to other collections?
 03309          if (un.ResolvedOp == UnaryOpExpr.ResolvedOpcode.SeqLength && GetAnyConst(un.E, consts) is string ss) {
 03310            return (BigInteger)(ss.Length);
 03311          }
 03312        } else if (e is MemberSelectExpr m) {
 03313          if (m.Member is ConstantField c && c.IsStatic && c.Rhs != null) {
 03314            // This aspect of type resolution happens before the check for cyclic references
 03315            // so we have to do a check here as well. If cyclic, null is silently returned,
 03316            // counting on the later error message to alert the user.
 03317            if (consts.Contains(c)) { return null; }
 03318            consts.Push(c);
 03319            Object o = GetAnyConst(c.Rhs, consts);
 03320            consts.Pop();
 03321            return o;
 03322          } else if (m.Member is SpecialField sf) {
 03323            string nm = sf.Name;
 03324            if (nm == "Floor") {
 03325              Object ee = GetAnyConst(m.Obj, consts);
 03326              if (ee != null && m.Obj.Type.IsNumericBased(Type.NumericPersuasion.Real)) {
 03327                ((BaseTypes.BigDec)ee).FloorCeiling(out var f, out _);
 03328                return f;
 03329              }
 03330            }
 03331          }
 03332        } else if (e is BinaryExpr bin) {
 03333          Object e0 = GetAnyConst(bin.E0, consts);
 03334          Object e1 = GetAnyConst(bin.E1, consts);
 03335          bool isBool = bin.E0.Type == Type.Bool && bin.E1.Type == Type.Bool;
 03336          bool shortCircuit = isBool && (bin.ResolvedOp == BinaryExpr.ResolvedOpcode.And
 03337                                         || bin.ResolvedOp == BinaryExpr.ResolvedOpcode.Or
 03338                                         || bin.ResolvedOp == BinaryExpr.ResolvedOpcode.Imp);
 03339
 03340          if (e0 == null || (!shortCircuit && e1 == null)) { return null; }
 03341          bool isAnyReal = bin.E0.Type.IsNumericBased(Type.NumericPersuasion.Real)
 03342                        && bin.E1.Type.IsNumericBased(Type.NumericPersuasion.Real);
 03343          bool isAnyInt = bin.E0.Type.IsNumericBased(Type.NumericPersuasion.Int)
 03344                       && bin.E1.Type.IsNumericBased(Type.NumericPersuasion.Int);
 03345          bool isReal = bin.Type.IsRealType;
 03346          bool isInt = bin.Type.IsIntegerType;
 03347          bool isBV = bin.E0.Type.IsBitVectorType;
 03348          int width = isBV ? bin.E0.Type.AsBitVectorType.Width : 0;
 03349          bool isString = e0 is string && e1 is string;
 03350          switch (bin.ResolvedOp) {
 03351            case BinaryExpr.ResolvedOpcode.Add:
 03352              if (isInt) {
 03353                return (BigInteger)e0 + (BigInteger)e1;
 03354              }
 03355
 03356              if (isBV) {
 03357                return ((BigInteger)e0 + (BigInteger)e1) & MaxBV(bin.Type);
 03358              }
 03359
 03360              if (isReal) {
 03361                return (BaseTypes.BigDec)e0 + (BaseTypes.BigDec)e1;
 03362              }
 03363
 03364              break;
 03365            case BinaryExpr.ResolvedOpcode.Concat:
 03366              if (isString) {
 03367                return (string)e0 + (string)e1;
 03368              }
 03369
 03370              break;
 03371            case BinaryExpr.ResolvedOpcode.Sub:
 03372              if (isInt) {
 03373                return (BigInteger)e0 - (BigInteger)e1;
 03374              }
 03375
 03376              if (isBV) {
 03377                return ((BigInteger)e0 - (BigInteger)e1) & MaxBV(bin.Type);
 03378              }
 03379
 03380              if (isReal) {
 03381                return (BaseTypes.BigDec)e0 - (BaseTypes.BigDec)e1;
 03382              }
 03383              // Allow a special case: If the result type is a newtype that is integer-based (i.e., isInt && !isInteger)
 03384              // then we generally do not fold the operations, because we do not determine whether the
 03385              // result of the operation satisfies the new type constraint. However, on the occasion that
 03386              // a newtype aliases int without a constraint, it occurs that a value of the newtype is initialized
 03387              // with a negative value, which is represented as "0 - N", that is, it comes to this case. It
 03388              // is a nuisance not to constant-fold the result, as not doing so can alter the determination
 03389              // of the representation type.
 03390              if (isAnyInt && AsUnconstrainedType(bin.Type) != null) {
 03391                return ((BigInteger)e0) - ((BigInteger)e1);
 03392              }
 03393              break;
 03394            case BinaryExpr.ResolvedOpcode.Mul:
 03395              if (isInt) {
 03396                return (BigInteger)e0 * (BigInteger)e1;
 03397              }
 03398
 03399              if (isBV) {
 03400                return ((BigInteger)e0 * (BigInteger)e1) & MaxBV(bin.Type);
 03401              }
 03402
 03403              if (isReal) {
 03404                return (BaseTypes.BigDec)e0 * (BaseTypes.BigDec)e1;
 03405              }
 03406
 03407              break;
 03408            case BinaryExpr.ResolvedOpcode.BitwiseAnd:
 03409              Contract.Assert(isBV);
 03410              return (BigInteger)e0 & (BigInteger)e1;
 03411            case BinaryExpr.ResolvedOpcode.BitwiseOr:
 03412              Contract.Assert(isBV);
 03413              return (BigInteger)e0 | (BigInteger)e1;
 03414            case BinaryExpr.ResolvedOpcode.BitwiseXor:
 03415              Contract.Assert(isBV);
 03416              return (BigInteger)e0 ^ (BigInteger)e1;
 03417            case BinaryExpr.ResolvedOpcode.Div:
 03418              if (isInt) {
 03419                if ((BigInteger)e1 == 0) {
 03420                  return null; // Divide by zero
 03421                } else {
 03422                  BigInteger a0 = (BigInteger)e0;
 03423                  BigInteger a1 = (BigInteger)e1;
 03424                  BigInteger d = a0 / a1;
 03425                  return a0 >= 0 || a0 == d * a1 ? d : a1 > 0 ? d - 1 : d + 1;
 03426                }
 03427              }
 03428              if (isBV) {
 03429                if ((BigInteger)e1 == 0) {
 03430                  return null; // Divide by zero
 03431                } else {
 03432                  return ((BigInteger)e0) / ((BigInteger)e1);
 03433                }
 03434              }
 03435              if (isReal) {
 03436                if ((BaseTypes.BigDec)e1 == BaseTypes.BigDec.ZERO) {
 03437                  return null; // Divide by zero
 03438                } else {
 03439                  // BigDec does not have divide and is not a representation of rationals, so we don't do constant foldi
 03440                  return null;
 03441                }
 03442              }
 03443
 03444              break;
 03445            case BinaryExpr.ResolvedOpcode.Mod:
 03446              if (isInt) {
 03447                if ((BigInteger)e1 == 0) {
 03448                  return null; // Mod by zero
 03449                } else {
 03450                  BigInteger a = BigInteger.Abs((BigInteger)e1);
 03451                  BigInteger d = (BigInteger)e0 % a;
 03452                  return (BigInteger)e0 >= 0 ? d : d + a;
 03453                }
 03454              }
 03455              if (isBV) {
 03456                if ((BigInteger)e1 == 0) {
 03457                  return null; // Mod by zero
 03458                } else {
 03459                  return (BigInteger)e0 % (BigInteger)e1;
 03460                }
 03461              }
 03462              break;
 03463            case BinaryExpr.ResolvedOpcode.LeftShift: {
 03464                if ((BigInteger)e1 < 0) {
 03465                  return null; // Negative shift
 03466                }
 03467                if ((BigInteger)e1 > bin.Type.AsBitVectorType.Width) {
 03468                  return null; // Shift is too large
 03469                }
 03470                return ((BigInteger)e0 << (int)(BigInteger)e1) & MaxBV(bin.E0.Type);
 03471              }
 03472            case BinaryExpr.ResolvedOpcode.RightShift: {
 03473                if ((BigInteger)e1 < 0) {
 03474                  return null; // Negative shift
 03475                }
 03476                if ((BigInteger)e1 > bin.Type.AsBitVectorType.Width) {
 03477                  return null; // Shift too large
 03478                }
 03479                return (BigInteger)e0 >> (int)(BigInteger)e1;
 03480              }
 03481            case BinaryExpr.ResolvedOpcode.And: {
 03482                if ((bool)e0 && e1 == null) {
 03483                  return null;
 03484                }
 03485
 03486                return (bool)e0 && (bool)e1;
 03487              }
 03488            case BinaryExpr.ResolvedOpcode.Or: {
 03489                if (!(bool)e0 && e1 == null) {
 03490                  return null;
 03491                }
 03492
 03493                return (bool)e0 || (bool)e1;
 03494              }
 03495            case BinaryExpr.ResolvedOpcode.Imp: { // ==> and <==
 03496                if ((bool)e0 && e1 == null) {
 03497                  return null;
 03498                }
 03499
 03500                return !(bool)e0 || (bool)e1;
 03501              }
 03502            case BinaryExpr.ResolvedOpcode.Iff: return (bool)e0 == (bool)e1; // <==>
 03503            case BinaryExpr.ResolvedOpcode.Gt:
 03504              if (isAnyInt) {
 03505                return (BigInteger)e0 > (BigInteger)e1;
 03506              }
 03507
 03508              if (isBV) {
 03509                return (BigInteger)e0 > (BigInteger)e1;
 03510              }
 03511
 03512              if (isAnyReal) {
 03513                return (BaseTypes.BigDec)e0 > (BaseTypes.BigDec)e1;
 03514              }
 03515
 03516              break;
 03517            case BinaryExpr.ResolvedOpcode.GtChar:
 03518              if (bin.E0.Type.IsCharType) {
 03519                return ((string)e0)[0] > ((string)e1)[0];
 03520              }
 03521
 03522              break;
 03523            case BinaryExpr.ResolvedOpcode.Ge:
 03524              if (isAnyInt) {
 03525                return (BigInteger)e0 >= (BigInteger)e1;
 03526              }
 03527
 03528              if (isBV) {
 03529                return (BigInteger)e0 >= (BigInteger)e1;
 03530              }
 03531
 03532              if (isAnyReal) {
 03533                return (BaseTypes.BigDec)e0 >= (BaseTypes.BigDec)e1;
 03534              }
 03535
 03536              break;
 03537            case BinaryExpr.ResolvedOpcode.GeChar:
 03538              if (bin.E0.Type.IsCharType) {
 03539                return ((string)e0)[0] >= ((string)e1)[0];
 03540              }
 03541
 03542              break;
 03543            case BinaryExpr.ResolvedOpcode.Lt:
 03544              if (isAnyInt) {
 03545                return (BigInteger)e0 < (BigInteger)e1;
 03546              }
 03547
 03548              if (isBV) {
 03549                return (BigInteger)e0 < (BigInteger)e1;
 03550              }
 03551
 03552              if (isAnyReal) {
 03553                return (BaseTypes.BigDec)e0 < (BaseTypes.BigDec)e1;
 03554              }
 03555
 03556              break;
 03557            case BinaryExpr.ResolvedOpcode.LtChar:
 03558              if (bin.E0.Type.IsCharType) {
 03559                return ((string)e0)[0] < ((string)e1)[0];
 03560              }
 03561
 03562              break;
 03563            case BinaryExpr.ResolvedOpcode.ProperPrefix:
 03564              if (isString) {
 03565                return ((string)e1).StartsWith((string)e0) && !((string)e1).Equals((string)e0);
 03566              }
 03567
 03568              break;
 03569            case BinaryExpr.ResolvedOpcode.Le:
 03570              if (isAnyInt) {
 03571                return (BigInteger)e0 <= (BigInteger)e1;
 03572              }
 03573
 03574              if (isBV) {
 03575                return (BigInteger)e0 <= (BigInteger)e1;
 03576              }
 03577
 03578              if (isAnyReal) {
 03579                return (BaseTypes.BigDec)e0 <= (BaseTypes.BigDec)e1;
 03580              }
 03581
 03582              break;
 03583            case BinaryExpr.ResolvedOpcode.LeChar:
 03584              if (bin.E0.Type.IsCharType) {
 03585                return ((string)e0)[0] <= ((string)e1)[0];
 03586              }
 03587
 03588              break;
 03589            case BinaryExpr.ResolvedOpcode.Prefix:
 03590              if (isString) {
 03591                return ((string)e1).StartsWith((string)e0);
 03592              }
 03593
 03594              break;
 03595            case BinaryExpr.ResolvedOpcode.EqCommon: {
 03596                if (isBool) {
 03597                  return (bool)e0 == (bool)e1;
 03598                } else if (isAnyInt || isBV) {
 03599                  return (BigInteger)e0 == (BigInteger)e1;
 03600                } else if (isAnyReal) {
 03601                  return (BaseTypes.BigDec)e0 == (BaseTypes.BigDec)e1;
 03602                } else if (bin.E0.Type.IsCharType) {
 03603                  return ((string)e0)[0] == ((string)e1)[0];
 03604                }
 03605                break;
 03606              }
 03607            case BinaryExpr.ResolvedOpcode.SeqEq:
 03608              if (isString) {
 03609                return (string)e0 == (string)e1;
 03610              }
 03611              break;
 03612            case BinaryExpr.ResolvedOpcode.SeqNeq:
 03613              if (isString) {
 03614                return (string)e0 != (string)e1;
 03615              }
 03616              break;
 03617            case BinaryExpr.ResolvedOpcode.NeqCommon: {
 03618                if (isBool) {
 03619                  return (bool)e0 != (bool)e1;
 03620                } else if (isAnyInt || isBV) {
 03621                  return (BigInteger)e0 != (BigInteger)e1;
 03622                } else if (isAnyReal) {
 03623                  return (BaseTypes.BigDec)e0 != (BaseTypes.BigDec)e1;
 03624                } else if (bin.E0.Type.IsCharType) {
 03625                  return ((string)e0)[0] != ((string)e1)[0];
 03626                } else if (isString) {
 03627                  return (string)e0 != (string)e1;
 03628                }
 03629                break;
 03630              }
 03631          }
 03632        } else if (e is ConversionExpr ce) {
 03633          object o = GetAnyConst(ce.E, consts);
 03634          if (o == null || ce.E.Type == ce.Type) {
 03635            return o;
 03636          }
 03637
 03638          if (ce.E.Type.IsNumericBased(Type.NumericPersuasion.Real) &&
 03639                ce.Type.IsBitVectorType) {
 03640            ((BaseTypes.BigDec)o).FloorCeiling(out var ff, out _);
 03641            if (ff < 0 || ff > MaxBV(ce.Type)) {
 03642              return null; // Out of range
 03643            }
 03644            if (((BaseTypes.BigDec)o) != BaseTypes.BigDec.FromBigInt(ff)) {
 03645              return null; // Out of range
 03646            }
 03647            return ff;
 03648          }
 03649
 03650          if (ce.E.Type.IsNumericBased(Type.NumericPersuasion.Real) &&
 03651                ce.Type.IsNumericBased(Type.NumericPersuasion.Int)) {
 03652            ((BaseTypes.BigDec)o).FloorCeiling(out var ff, out _);
 03653            if (AsUnconstrainedType(ce.Type) == null) {
 03654              return null;
 03655            }
 03656
 03657            if (((BaseTypes.BigDec)o) != BaseTypes.BigDec.FromBigInt(ff)) {
 03658              return null; // Argument not an integer
 03659            }
 03660            return ff;
 03661          }
 03662
 03663          if (ce.E.Type.IsBitVectorType &&
 03664                ce.Type.IsNumericBased(Type.NumericPersuasion.Int)) {
 03665            if (AsUnconstrainedType(ce.Type) == null) {
 03666              return null;
 03667            }
 03668
 03669            return o;
 03670          }
 03671
 03672          if (ce.E.Type.IsBitVectorType &&
 03673                ce.Type.IsNumericBased(Type.NumericPersuasion.Real)) {
 03674            if (AsUnconstrainedType(ce.Type) == null) {
 03675              return null;
 03676            }
 03677
 03678            return BaseTypes.BigDec.FromBigInt((BigInteger)o);
 03679          }
 03680
 03681          if (ce.E.Type.IsNumericBased(Type.NumericPersuasion.Int) &&
 03682                ce.Type.IsBitVectorType) {
 03683            BigInteger b = (BigInteger)o;
 03684            if (b < 0 || b > MaxBV(ce.Type)) {
 03685              return null; // Argument out of range
 03686            }
 03687            return o;
 03688          }
 03689
 03690          if (ce.E.Type.IsNumericBased(Type.NumericPersuasion.Int) &&
 03691                ce.Type.IsNumericBased(Type.NumericPersuasion.Int)) {
 03692            // This case includes int-based newtypes to int-based new types
 03693            if (AsUnconstrainedType(ce.Type) == null) {
 03694              return null;
 03695            }
 03696
 03697            return o;
 03698          }
 03699
 03700          if (ce.E.Type.IsNumericBased(Type.NumericPersuasion.Real) &&
 03701                ce.Type.IsNumericBased(Type.NumericPersuasion.Real)) {
 03702            // This case includes real-based newtypes to real-based new types
 03703            if (AsUnconstrainedType(ce.Type) == null) {
 03704              return null;
 03705            }
 03706
 03707            return o;
 03708          }
 03709
 03710          if (ce.E.Type.IsBitVectorType && ce.Type.IsBitVectorType) {
 03711            BigInteger b = (BigInteger)o;
 03712            if (b < 0 || b > MaxBV(ce.Type)) {
 03713              return null; // Argument out of range
 03714            }
 03715            return o;
 03716          }
 03717
 03718          if (ce.E.Type.IsNumericBased(Type.NumericPersuasion.Int) &&
 03719                ce.Type.IsNumericBased(Type.NumericPersuasion.Real)) {
 03720            if (AsUnconstrainedType(ce.Type) == null) {
 03721              return null;
 03722            }
 03723
 03724            return BaseTypes.BigDec.FromBigInt((BigInteger)o);
 03725          }
 03726
 03727          if (ce.E.Type.IsCharType && ce.Type.IsNumericBased(Type.NumericPersuasion.Int)) {
 03728            char c = ((String)o)[0];
 03729            if (AsUnconstrainedType(ce.Type) == null) {
 03730              return null;
 03731            }
 03732
 03733            return new BigInteger(((string)o)[0]);
 03734          }
 03735
 03736          if (ce.E.Type.IsCharType && ce.Type.IsBitVectorType) {
 03737            char c = ((String)o)[0];
 03738            if ((int)c > MaxBV(ce.Type)) {
 03739              return null; // Argument out of range
 03740            }
 03741            return new BigInteger(((string)o)[0]);
 03742          }
 03743
 03744          if ((ce.E.Type.IsNumericBased(Type.NumericPersuasion.Int) || ce.E.Type.IsBitVectorType) &&
 03745                ce.Type.IsCharType) {
 03746            BigInteger b = (BigInteger)o;
 03747            if (b < BigInteger.Zero || b > new BigInteger(65535)) {
 03748              return null; // Argument out of range
 03749            }
 03750            return ((char)(int)b).ToString();
 03751          }
 03752
 03753          if (ce.E.Type.IsCharType &&
 03754              ce.Type.IsNumericBased(Type.NumericPersuasion.Real)) {
 03755            if (AsUnconstrainedType(ce.Type) == null) {
 03756              return null;
 03757            }
 03758
 03759            return BaseTypes.BigDec.FromInt(((string)o)[0]);
 03760          }
 03761
 03762          if (ce.E.Type.IsNumericBased(Type.NumericPersuasion.Real) &&
 03763                ce.Type.IsCharType) {
 03764            ((BaseTypes.BigDec)o).FloorCeiling(out var ff, out _);
 03765            if (((BaseTypes.BigDec)o) != BaseTypes.BigDec.FromBigInt(ff)) {
 03766              return null; // Argument not an integer
 03767            }
 03768            if (ff < BigInteger.Zero || ff > new BigInteger(65535)) {
 03769              return null; // Argument out of range
 03770            }
 03771            return ((char)(int)ff).ToString();
 03772          }
 03773
 03774        } else if (e is SeqSelectExpr sse) {
 03775          var b = GetAnyConst(sse.Seq, consts) as string;
 03776          BigInteger index = (BigInteger)GetAnyConst(sse.E0, consts);
 03777          if (b == null) {
 03778            return null;
 03779          }
 03780
 03781          if (index < 0 || index >= b.Length || index > Int32.MaxValue) {
 03782            return null; // Index out of range
 03783          }
 03784          return b[(int)index].ToString();
 03785        } else if (e is ITEExpr ite) {
 03786          Object b = GetAnyConst(ite.Test, consts);
 03787          if (b == null) {
 03788            return null;
 03789          }
 03790
 03791          return ((bool)b) ? GetAnyConst(ite.Thn, consts) : GetAnyConst(ite.Els, consts);
 03792        } else if (e is ConcreteSyntaxExpression n) {
 03793          return GetAnyConst(n.ResolvedExpression, consts);
 03794        } else {
 03795          return null;
 03796        }
 03797        return null;
 03798      };
 03799      GetConst = (Expression e) => {
 03800        Object ee = GetAnyConst(e.Resolved ?? e, new Stack<ConstantField>());
 03801        return ee as BigInteger?;
 03802      };
 3803      // Now, then, let's go through them types.
 3804      // FIXME - should first go through the bounds to find the most constraining values
 3805      // then check those values against the possible types. Note that also presumes the types are in order.
 03806      BigInteger? lowest = null;
 03807      BigInteger? highest = null;
 03808      foreach (var bound in bounds) {
 03809        if (bound is ComprehensionExpr.IntBoundedPool) {
 03810          var bnd = (ComprehensionExpr.IntBoundedPool)bound;
 03811          if (bnd.LowerBound != null) {
 03812            BigInteger? lower = GetConst(bnd.LowerBound);
 03813            if (lower != null && (lowest == null || lower < lowest)) {
 03814              lowest = lower;
 03815            }
 03816          }
 03817          if (bnd.UpperBound != null) {
 03818            BigInteger? upper = GetConst(bnd.UpperBound);
 03819            if (upper != null && (highest == null || upper > highest)) {
 03820              highest = upper;
 03821            }
 03822          }
 03823        }
 03824      }
 03825      foreach (var nativeT in nativeTypeChoices ?? NativeTypes) {
 03826        bool lowerOk = (lowest != null && nativeT.LowerBound <= lowest);
 03827        bool upperOk = (highest != null && nativeT.UpperBound >= highest);
 03828        if (lowerOk && upperOk) {
 03829          bigEnoughNativeTypes.Add(nativeT);
 03830        } else if (nativeTypeChoices != null) {
 03831          reporter.Error(MessageSource.Resolver, dd,
 03832            "Dafny's heuristics failed to confirm '{0}' to be a compatible native type.  " +
 03833            "Hint: try writing a newtype constraint of the form 'i:int | lowerBound <= i < upperBound && (...any additio
 03834            nativeT.Name);
 03835          return;
 3836        }
 03837      }
 3838
 3839      // Finally, of the big-enough native types, pick the first one that is
 3840      // supported by the selected target compiler.
 03841      foreach (var nativeT in bigEnoughNativeTypes) {
 03842        if (Options.Backend.SupportedNativeTypes.Contains(nativeT.Name)) {
 03843          dd.NativeType = nativeT;
 03844          break;
 3845        }
 03846      }
 03847      if (dd.NativeType != null) {
 3848        // Give an info message saying which type was selected--unless the user requested
 3849        // one particular native type, in which case that must have been the one picked.
 03850        if (nativeTypeChoices != null && nativeTypeChoices.Count == 1) {
 03851          Contract.Assert(dd.NativeType == nativeTypeChoices[0]);
 03852        } else {
 03853          reporter.Info(MessageSource.Resolver, dd.tok, "newtype " + dd.Name + " resolves as {:nativeType \"" + dd.Nativ
 03854        }
 03855      } else if (nativeTypeChoices != null) {
 03856        reporter.Error(MessageSource.Resolver, dd,
 03857          "None of the types given in :nativeType arguments is supported by the current compilation target. Try supplyin
 03858      } else if (mustUseNativeType) {
 03859        reporter.Error(MessageSource.Resolver, dd,
 03860          "Dafny's heuristics cannot find a compatible native type.  " +
 03861          "Hint: try writing a newtype constraint of the form 'i:int | lowerBound <= i < upperBound && (...any additiona
 03862      }
 03863    }
 3864
 3865    /// <summary>
 3866    /// Check that the 'older' modifier on parameters is used correctly and report any errors of the contrary.
 3867    /// </summary>
 03868    void CheckOlderParameters(Function f) {
 3869      Contract.Requires(f != null);
 3870
 03871      if (!f.ResultType.IsBoolType || f is PrefixPredicate || f is ExtremePredicate) {
 3872        // parameters are not allowed to be marked 'older'
 03873        foreach (var formal in f.Formals) {
 03874          if (formal.IsOlder) {
 03875            reporter.Error(MessageSource.Resolver, formal.tok, "only predicates and two-state predicates are allowed 'ol
 03876          }
 03877        }
 03878      }
 03879    }
 3880
 3881    // ------------------------------------------------------------------------------------------------------
 3882    // ----- CheckExpression --------------------------------------------------------------------------------
 3883    // ------------------------------------------------------------------------------------------------------
 3884    #region CheckExpression
 3885    /// <summary>
 3886    /// This method computes ghost interests in the statement portion of StmtExpr's and
 3887    /// checks for hint restrictions in any CalcStmt.
 3888    /// </summary>
 21843889    void CheckExpression(Expression expr, Resolver resolver, ICodeContext codeContext) {
 3890      Contract.Requires(expr != null);
 3891      Contract.Requires(resolver != null);
 3892      Contract.Requires(codeContext != null);
 21843893      var v = new CheckExpression_Visitor(resolver, codeContext);
 21843894      v.Visit(expr);
 21843895    }
 3896    /// <summary>
 3897    /// This method computes ghost interests in the statement portion of StmtExpr's and
 3898    /// checks for hint restrictions in any CalcStmt. In any ghost context, it also
 3899    /// changes the bound variables of all let- and let-such-that expressions to ghost.
 3900    /// It also performs substitutions in DefaultValueExpression's.
 3901    /// </summary>
 18843902    void CheckExpression(Statement stmt, Resolver resolver, ICodeContext codeContext) {
 3903      Contract.Requires(stmt != null);
 3904      Contract.Requires(resolver != null);
 3905      Contract.Requires(codeContext != null);
 18843906      var v = new CheckExpression_Visitor(resolver, codeContext);
 18843907      v.Visit(stmt);
 18843908    }
 3909    class CheckExpression_Visitor : ResolverBottomUpVisitor {
 3910      readonly ICodeContext CodeContext;
 3911      public CheckExpression_Visitor(Resolver resolver, ICodeContext codeContext)
 81363912        : base(resolver) {
 3913        Contract.Requires(resolver != null);
 3914        Contract.Requires(codeContext != null);
 40683915        CodeContext = codeContext;
 40683916      }
 7324643917      protected override void VisitOneExpr(Expression expr) {
 7324643918        if (expr is StmtExpr) {
 03919          var e = (StmtExpr)expr;
 03920          resolver.ComputeGhostInterest(e.S, true, "a statement expression", CodeContext);
 7324643921        } else if (expr is LetExpr) {
 03922          var e = (LetExpr)expr;
 03923          if (CodeContext.IsGhost) {
 03924            foreach (var bv in e.BoundVars) {
 03925              bv.MakeGhost();
 03926            }
 03927          }
 03928        }
 7324643929      }
 3930
 1576223931      protected override void VisitOneStmt(Statement stmt) {
 1576223932        if (stmt is CalcStmt calc) {
 03933          foreach (var h in calc.Hints) {
 03934            resolver.CheckLocalityUpdates(h, new HashSet<LocalVariable>(), "a hint");
 03935          }
 1576223936        } else if (stmt is AssertStmt astmt && astmt.Proof != null) {
 03937          resolver.CheckLocalityUpdates(astmt.Proof, new HashSet<LocalVariable>(), "an assert-by body");
 1576223938        } else if (stmt is ForallStmt forall && forall.Body != null) {
 03939          resolver.CheckLocalityUpdates(forall.Body, new HashSet<LocalVariable>(), "a forall statement");
 03940        }
 1576223941      }
 3942    }
 3943    #endregion
 3944
 3945    // ------------------------------------------------------------------------------------------------------
 3946    // ----- FuelAdjustmentChecks ---------------------------------------------------------------------------
 3947    // ------------------------------------------------------------------------------------------------------
 3948    #region FuelAdjustmentChecks
 3949
 798553950    protected void CheckForFuelAdjustments(IToken tok, Attributes attrs, ModuleDefinition currentModule) {
 798553951      List<List<Expression>> results = Attributes.FindAllExpressions(attrs, "fuel");
 3952
 798553953      if (results != null) {
 03954        foreach (List<Expression> args in results) {
 03955          if (args != null && args.Count >= 2) {
 3956            // Try to extract the function from the first argument
 03957            MemberSelectExpr selectExpr = args[0].Resolved as MemberSelectExpr;
 03958            if (selectExpr != null) {
 03959              Function f = selectExpr.Member as Function;
 03960              if (f != null) {
 03961                f.IsFueled = true;
 03962                if (args.Count >= 3) {
 03963                  LiteralExpr literalLow = args[1] as LiteralExpr;
 03964                  LiteralExpr literalHigh = args[2] as LiteralExpr;
 03965                  if (literalLow != null && literalLow.Value is BigInteger && literalHigh != null && literalHigh.Value i
 03966                    BigInteger low = (BigInteger)literalLow.Value;
 03967                    BigInteger high = (BigInteger)literalHigh.Value;
 03968                    if (!(high == low + 1 || (low == 0 && high == 0))) {
 03969                      reporter.Error(MessageSource.Resolver, tok, "fuel setting for function {0} must have high value ==
 03970                    }
 03971                  }
 03972                }
 03973              }
 03974            }
 03975          }
 03976        }
 03977      }
 798553978    }
 3979
 3980    public class FuelAdjustment_Context {
 3981      public ModuleDefinition currentModule;
 18843982      public FuelAdjustment_Context(ModuleDefinition currentModule) {
 9423983        this.currentModule = currentModule;
 9423984      }
 3985    }
 3986
 3987    class FuelAdjustment_Visitor : ResolverTopDownVisitor<FuelAdjustment_Context> {
 3988      public FuelAdjustment_Visitor(Resolver resolver)
 18843989        : base(resolver) {
 3990        Contract.Requires(resolver != null);
 9423991      }
 3992
 788113993      protected override bool VisitOneStmt(Statement stmt, ref FuelAdjustment_Context st) {
 788113994        resolver.CheckForFuelAdjustments(stmt.Tok, stmt.Attributes, st.currentModule);
 788113995        return true;
 788113996      }
 3997    }
 3998
 3999    #endregion FuelAdjustmentChecks
 4000
 4001    // ------------------------------------------------------------------------------------------------------
 4002    // ----- ExtremePredicateChecks -------------------------------------------------------------------------
 4003    // ------------------------------------------------------------------------------------------------------
 4004    #region ExtremePredicateChecks
 4005    enum CallingPosition { Positive, Negative, Neither }
 04006    static CallingPosition Invert(CallingPosition cp) {
 04007      switch (cp) {
 04008        case CallingPosition.Positive: return CallingPosition.Negative;
 04009        case CallingPosition.Negative: return CallingPosition.Positive;
 04010        default: return CallingPosition.Neither;
 4011      }
 04012    }
 4013
 4014    class FindFriendlyCalls_Visitor : ResolverTopDownVisitor<CallingPosition> {
 4015      public readonly bool IsCoContext;
 4016      public readonly bool ContinuityIsImportant;
 4017      public FindFriendlyCalls_Visitor(Resolver resolver, bool co, bool continuityIsImportant)
 04018        : base(resolver) {
 4019        Contract.Requires(resolver != null);
 04020        this.IsCoContext = co;
 04021        this.ContinuityIsImportant = continuityIsImportant;
 04022      }
 4023
 04024      protected override bool VisitOneExpr(Expression expr, ref CallingPosition cp) {
 04025        if (expr is UnaryOpExpr) {
 04026          var e = (UnaryOpExpr)expr;
 04027          if (e.Op == UnaryOpExpr.Opcode.Not) {
 4028            // for the sub-parts, use Invert(cp)
 04029            cp = Invert(cp);
 04030            return true;
 4031          }
 04032        } else if (expr is BinaryExpr) {
 04033          var e = (BinaryExpr)expr;
 04034          switch (e.ResolvedOp) {
 4035            case BinaryExpr.ResolvedOpcode.And:
 4036            case BinaryExpr.ResolvedOpcode.Or:
 04037              return true;  // do the sub-parts with the same "cp"
 4038            case BinaryExpr.ResolvedOpcode.Imp:
 04039              Visit(e.E0, Invert(cp));
 04040              Visit(e.E1, cp);
 04041              return false;  // don't recurse (again) on the sub-parts
 4042            default:
 04043              break;
 4044          }
 04045        } else if (expr is NestedMatchExpr) {
 04046          var e = (NestedMatchExpr)expr;
 04047          Visit(e.Source, CallingPosition.Neither);
 04048          var theCp = cp;
 04049          e.Cases.Iter(kase => Visit(kase.Body, theCp));
 04050          return false;
 04051        } else if (expr is MatchExpr) {
 04052          var e = (MatchExpr)expr;
 04053          Visit(e.Source, CallingPosition.Neither);
 04054          var theCp = cp;
 04055          e.Cases.Iter(kase => Visit(kase.Body, theCp));
 04056          return false;
 04057        } else if (expr is ITEExpr) {
 04058          var e = (ITEExpr)expr;
 04059          Visit(e.Test, CallingPosition.Neither);
 04060          Visit(e.Thn, cp);
 04061          Visit(e.Els, cp);
 04062          return false;
 04063        } else if (expr is LetExpr) {
 04064          var e = (LetExpr)expr;
 04065          foreach (var rhs in e.RHSs) {
 04066            Visit(rhs, CallingPosition.Neither);
 04067          }
 04068          var cpBody = cp;
 04069          if (!e.Exact) {
 4070            // a let-such-that expression introduces an existential that may depend on the _k in a least/greatest predic
 04071            if (IsCoContext && cp == CallingPosition.Positive) {
 04072              cpBody = CallingPosition.Neither;
 04073            } else if (!IsCoContext && cp == CallingPosition.Negative) {
 04074              cpBody = CallingPosition.Neither;
 04075            }
 04076          }
 04077          Visit(e.Body, cpBody);
 04078          return false;
 04079        } else if (expr is QuantifierExpr) {
 04080          var e = (QuantifierExpr)expr;
 04081          Contract.Assert(e.SplitQuantifier == null); // No split quantifiers during resolution
 04082          var cpos = IsCoContext ? cp : Invert(cp);
 04083          if (ContinuityIsImportant) {
 04084            if ((cpos == CallingPosition.Positive && e is ExistsExpr) || (cpos == CallingPosition.Negative && e is Foral
 04085              if (e.Bounds.Exists(bnd => bnd == null || (bnd.Virtues & ComprehensionExpr.BoundedPool.PoolVirtues.Finite)
 4086                // To ensure continuity of extreme predicates, don't allow calls under an existential (resp. universal) 
 4087                // for greatest (resp. least) predicates).
 04088                cp = CallingPosition.Neither;
 04089              }
 04090            }
 04091          }
 04092          Visit(e.LogicalBody(), cp);
 04093          return false;
 04094        } else if (expr is StmtExpr) {
 04095          var e = (StmtExpr)expr;
 04096          Visit(e.E, cp);
 04097          Visit(e.S, CallingPosition.Neither);
 04098          return false;
 04099        } else if (expr is ConcreteSyntaxExpression) {
 4100          // do the sub-parts with the same "cp"
 04101          return true;
 4102        }
 4103        // do the sub-parts with cp := Neither
 04104        cp = CallingPosition.Neither;
 04105        return true;
 04106      }
 4107    }
 4108
 04109    void KNatMismatchError(IToken tok, string contextName, ExtremePredicate.KType contextK, ExtremePredicate.KType calle
 04110      var hint = contextK == ExtremePredicate.KType.Unspecified ? string.Format(" (perhaps try declaring '{0}' as '{0}[n
 04111      reporter.Error(MessageSource.Resolver, tok,
 04112        "this call does not type check, because the context uses a _k parameter of type {0} whereas the callee uses a _k
 04113        contextK == ExtremePredicate.KType.Nat ? "nat" : "ORDINAL",
 04114        calleeK == ExtremePredicate.KType.Nat ? "nat" : "ORDINAL",
 04115        hint);
 04116    }
 4117
 4118    class ExtremePredicateChecks_Visitor : FindFriendlyCalls_Visitor {
 4119      readonly ExtremePredicate context;
 4120      public ExtremePredicateChecks_Visitor(Resolver resolver, ExtremePredicate context)
 04121        : base(resolver, context is GreatestPredicate, context.KNat) {
 4122        Contract.Requires(resolver != null);
 4123        Contract.Requires(context != null);
 04124        this.context = context;
 04125      }
 04126      protected override bool VisitOneExpr(Expression expr, ref CallingPosition cp) {
 04127        if (expr is FunctionCallExpr) {
 04128          var e = (FunctionCallExpr)expr;
 04129          if (ModuleDefinition.InSameSCC(context, e.Function)) {
 4130            // we're looking at a recursive call
 04131            if (!(context is LeastPredicate ? e.Function is LeastPredicate : e.Function is GreatestPredicate)) {
 04132              resolver.reporter.Error(MessageSource.Resolver, e, "a recursive call from a {0} can go only to other {0}s"
 04133            } else if (context.KNat != ((ExtremePredicate)e.Function).KNat) {
 04134              resolver.KNatMismatchError(e.tok, context.Name, context.TypeOfK, ((ExtremePredicate)e.Function).TypeOfK);
 04135            } else if (cp != CallingPosition.Positive) {
 04136              var msg = string.Format("a {0} can be called recursively only in positive positions", context.WhatKind);
 04137              if (ContinuityIsImportant && cp == CallingPosition.Neither) {
 4138                // this may be inside an non-friendly quantifier
 04139                msg += string.Format(" and cannot sit inside an unbounded {0} quantifier", context is LeastPredicate ? "
 04140              } else {
 4141                // we don't care about the continuity restriction or
 4142                // the extreme-call is not inside an quantifier, so don't bother mentioning the part of existentials/uni
 04143              }
 04144              resolver.reporter.Error(MessageSource.Resolver, e, msg);
 04145            } else {
 04146              e.CoCall = FunctionCallExpr.CoCallResolution.Yes;
 04147              resolver.reporter.Info(MessageSource.Resolver, e.tok, e.Function.Name + "#[_k - 1]");
 04148            }
 04149          }
 4150          // do the sub-parts with cp := Neither
 04151          cp = CallingPosition.Neither;
 04152          return true;
 4153        }
 04154        return base.VisitOneExpr(expr, ref cp);
 04155      }
 04156      protected override bool VisitOneStmt(Statement stmt, ref CallingPosition st) {
 04157        if (stmt is CallStmt) {
 04158          var s = (CallStmt)stmt;
 04159          if (ModuleDefinition.InSameSCC(context, s.Method)) {
 4160            // we're looking at a recursive call
 04161            resolver.reporter.Error(MessageSource.Resolver, stmt.Tok, "a recursive call from a {0} can go only to other 
 04162          }
 4163          // do the sub-parts with the same "cp"
 04164          return true;
 04165        } else {
 04166          return base.VisitOneStmt(stmt, ref st);
 4167        }
 04168      }
 4169    }
 4170
 04171    void ExtremePredicateChecks(Expression expr, ExtremePredicate context, CallingPosition cp) {
 4172      Contract.Requires(expr != null);
 4173      Contract.Requires(context != null);
 04174      var v = new ExtremePredicateChecks_Visitor(this, context);
 04175      v.Visit(expr, cp);
 04176    }
 4177    #endregion ExtremePredicateChecks
 4178
 4179    // ------------------------------------------------------------------------------------------------------
 4180    // ----- ExtremeLemmaChecks -----------------------------------------------------------------------------
 4181    // ------------------------------------------------------------------------------------------------------
 4182    #region ExtremeLemmaChecks
 4183    class ExtremeLemmaChecks_Visitor : ResolverBottomUpVisitor {
 4184      ExtremeLemma context;
 4185      public ExtremeLemmaChecks_Visitor(Resolver resolver, ExtremeLemma context)
 04186        : base(resolver) {
 4187        Contract.Requires(resolver != null);
 4188        Contract.Requires(context != null);
 04189        this.context = context;
 04190      }
 04191      protected override void VisitOneStmt(Statement stmt) {
 04192        if (stmt is CallStmt) {
 04193          var s = (CallStmt)stmt;
 04194          if (s.Method is ExtremeLemma || s.Method is PrefixLemma) {
 4195            // all is cool
 04196          } else {
 4197            // the call goes from an extreme lemma context to a non-extreme-lemma callee
 04198            if (ModuleDefinition.InSameSCC(context, s.Method)) {
 4199              // we're looking at a recursive call (to a non-extreme-lemma)
 04200              resolver.reporter.Error(MessageSource.Resolver, s.Tok, "a recursive call from a {0} can go only to other {
 04201            }
 04202          }
 04203        }
 04204      }
 04205      protected override void VisitOneExpr(Expression expr) {
 04206        if (expr is FunctionCallExpr) {
 04207          var e = (FunctionCallExpr)expr;
 4208          // the call goes from a greatest lemma context to a non-greatest-lemma callee
 04209          if (ModuleDefinition.InSameSCC(context, e.Function)) {
 4210            // we're looking at a recursive call (to a non-greatest-lemma)
 04211            resolver.reporter.Error(MessageSource.Resolver, e.tok, "a recursive call from a greatest lemma can go only t
 04212          }
 04213        }
 04214      }
 4215    }
 04216    void ExtremeLemmaChecks(Statement stmt, ExtremeLemma context) {
 4217      Contract.Requires(stmt != null);
 4218      Contract.Requires(context != null);
 04219      var v = new ExtremeLemmaChecks_Visitor(this, context);
 04220      v.Visit(stmt);
 04221    }
 04222    void ExtremeLemmaChecks(Expression expr, ExtremeLemma context) {
 4223      Contract.Requires(context != null);
 04224      if (expr == null) {
 04225        return;
 4226      }
 4227
 04228      var v = new ExtremeLemmaChecks_Visitor(this, context);
 04229      v.Visit(expr);
 04230    }
 4231    #endregion ExtremeLemmaChecks
 4232
 4233    // ------------------------------------------------------------------------------------------------------
 4234    // ----- CheckTypeCharacteristics -----------------------------------------------------------------------
 4235    // ------------------------------------------------------------------------------------------------------
 4236    #region CheckTypeCharacteristics
 18844237    void CheckTypeCharacteristics_Stmt(Statement stmt, bool isGhost) {
 4238      Contract.Requires(stmt != null);
 18844239      var v = new CheckTypeCharacteristics_Visitor(this);
 18844240      v.Visit(stmt, isGhost);
 18844241    }
 4484242    void CheckTypeCharacteristics_Expr(Expression expr, bool isGhost) {
 4243      Contract.Requires(expr != null);
 4484244      var v = new CheckTypeCharacteristics_Visitor(this);
 4484245      v.Visit(expr, isGhost);
 4484246    }
 69264247    public void CheckTypeCharacteristics_Type(IToken tok, Type type, bool isGhost) {
 4248      Contract.Requires(tok != null);
 4249      Contract.Requires(type != null);
 69264250      var v = new CheckTypeCharacteristics_Visitor(this);
 69264251      v.VisitType(tok, type, isGhost);
 69264252    }
 4253
 4254    /// <summary>
 4255    /// This visitor checks that type characteristics are respected in all (implicitly or explicitly)
 4256    /// declared types. Note that equality-support is checked only in compiled contexts.
 4257    /// In addition, this visitor checks that operations that require equality are applied to
 4258    /// types that really do support equality; this, too, is checked only in compiled contexts.
 4259    /// </summary>
 4260    class CheckTypeCharacteristics_Visitor : ResolverTopDownVisitor<bool> {
 4261      public CheckTypeCharacteristics_Visitor(Resolver resolver)
 185164262        : base(resolver) {
 4263        Contract.Requires(resolver != null);
 92584264      }
 1576224265      protected override bool VisitOneStmt(Statement stmt, ref bool inGhostContext) {
 1585364266        if (stmt.IsGhost) {
 9144267          inGhostContext = true;
 9144268        }
 4269        // In the sequel, do two things:
 4270        //  * Call VisitType on any type that occurs in the statement
 4271        //  * If the statement introduces ghost components, handle those components here
 4272        //    rather than letting the default visitor handle them
 2033464273        if (stmt is VarDeclStmt) {
 457244274          var s = (VarDeclStmt)stmt;
 2792584275          foreach (var v in s.Locals) {
 473624276            VisitType(v.Tok, v.Type, inGhostContext || v.IsGhost);
 473624277          }
 1576224278        } else if (stmt is VarDeclPattern) {
 04279          var s = (VarDeclPattern)stmt;
 04280          foreach (var v in s.LocalVars) {
 04281            VisitType(v.Tok, v.Type, inGhostContext || v.IsGhost);
 04282          }
 1605364283        } else if (stmt is AssignStmt) {
 486384284          var s = (AssignStmt)stmt;
 519384285          if (s.Rhs is TypeRhs tRhs) {
 33004286            VisitType(tRhs.Tok, tRhs.Type, inGhostContext);
 33004287          }
 1118984288        } else if (stmt is AssignSuchThatStmt) {
 04289          var s = (AssignSuchThatStmt)stmt;
 04290          Visit(Attributes.SubExpressions(s.Attributes), true);
 04291          Visit(s.Expr, inGhostContext);
 04292          foreach (var lhs in s.Lhss) {
 04293            Visit(lhs, inGhostContext);
 04294          }
 04295          return false;
 636104296        } else if (stmt is WhileStmt) {
 3504297          var s = (WhileStmt)stmt;
 4298          // all subexpressions are ghost, except the guard
 3504299          Visit(s.LoopSpecificationExpressions, true);
 7004300          if (s.Guard != null) {
 3504301            Visit(s.Guard, inGhostContext);
 3504302          }
 3504303          Visit(s.SubStatements, inGhostContext);
 3504304          return false;
 629104305        } else if (stmt is AlternativeLoopStmt) {
 04306          var s = (AlternativeLoopStmt)stmt;
 4307          // all subexpressions are ghost, except the guards
 04308          Visit(s.LoopSpecificationExpressions, true);
 04309          foreach (var alt in s.Alternatives) {
 04310            Visit(alt.Guard, inGhostContext);
 04311          }
 04312          Visit(s.SubStatements, inGhostContext);
 04313          return false;
 632304314        } else if (stmt is ForLoopStmt) {
 3204315          var s = (ForLoopStmt)stmt;
 4316          // all subexpressions are ghost, except the bounds
 3204317          Visit(s.LoopSpecificationExpressions, true);
 3204318          Visit(s.Start, inGhostContext);
 6404319          if (s.End != null) {
 3204320            Visit(s.End, inGhostContext);
 3204321          }
 3204322          Visit(s.SubStatements, inGhostContext);
 3204323          return false;
 657964324        } else if (stmt is CallStmt) {
 32064325          var s = (CallStmt)stmt;
 32064326          CheckTypeInstantiation(s.Tok, s.Method.WhatKind, s.Method.Name, s.Method.TypeArgs, s.MethodSelect.TypeApplicat
 4327          // recursively visit all subexpressions, noting that some of them may correspond to ghost formal parameters
 32064328          Contract.Assert(s.Lhs.Count == s.Method.Outs.Count);
 167504329          for (var i = 0; i < s.Method.Outs.Count; i++) {
 34464330            Visit(s.Lhs[i], inGhostContext || s.Method.Outs[i].IsGhost);
 34464331          }
 32064332          Visit(s.Receiver, inGhostContext);
 32064333          Contract.Assert(s.Args.Count == s.Method.Ins.Count);
 271124334          for (var i = 0; i < s.Method.Ins.Count; i++) {
 69004335            Visit(s.Args[i], inGhostContext || s.Method.Ins[i].IsGhost);
 69004336          }
 32064337          return false;
 593844338        } else if (stmt is ForallStmt) {
 04339          var s = (ForallStmt)stmt;
 04340          foreach (var v in s.BoundVars) {
 04341            VisitType(v.Tok, v.Type, inGhostContext);
 04342          }
 4343          // do substatements and subexpressions, noting that ensures clauses are ghost
 04344          Visit(Attributes.SubExpressions(s.Attributes), true);
 04345          if (s.Range != null) {
 04346            Visit(s.Range, inGhostContext);
 04347          }
 04348          foreach (var ee in s.Ens) {
 04349            Visit(Attributes.SubExpressions(ee.Attributes), true);
 04350            Visit(ee.E, true);
 04351          }
 04352          Visit(s.SubStatements, inGhostContext);
 04353          return false;
 598884354        } else if (stmt is ExpectStmt) {
 5044355          var s = (ExpectStmt)stmt;
 5044356          Visit(Attributes.SubExpressions(s.Attributes), true);
 5044357          Visit(s.Expr, inGhostContext);
 10084358          if (s.Message != null) {
 5044359            Visit(s.Message, inGhostContext);
 5044360          }
 5044361          return false;
 4362        }
 1532424363        return true;
 1576224364      }
 4365
 6196794366      protected override bool VisitOneExpr(Expression expr, ref bool inGhostContext) {
 4367        // Do two things:
 4368        //  * Call VisitType on any type that occurs in the statement
 4369        //  * If the expression introduces ghost components, handle those components here
 4370        //    rather than letting the default visitor handle them
 6439654371        if (expr is BinaryExpr && !inGhostContext) {
 242864372          var e = (BinaryExpr)expr;
 242864373          var t0 = e.E0.Type.NormalizeExpand();
 242864374          var t1 = e.E1.Type.NormalizeExpand();
 242864375          switch (e.Op) {
 4376            case BinaryExpr.Opcode.Eq:
 4377            case BinaryExpr.Opcode.Neq:
 4378              // First, check some special cases that can always be compared against--for example, a datatype value (lik
 192444379              if (CanCompareWith(e.E0)) {
 4380                // that's cool
 96224381              } else if (CanCompareWith(e.E1)) {
 4382                // oh yeah!
 04383              } else if (!t0.PartiallySupportsEquality) {
 04384                resolver.reporter.Error(MessageSource.Resolver, e.E0, "{0} can only be applied to expressions of types t
 04385              } else if (!t1.PartiallySupportsEquality) {
 04386                resolver.reporter.Error(MessageSource.Resolver, e.E1, "{0} can only be applied to expressions of types t
 04387              }
 96224388              break;
 4389            default:
 146644390              switch (e.ResolvedOp) {
 4391                // Note, all operations on sets, multisets, and maps are guaranteed to work because of restrictions plac
 4392                // these types are instantiated.  (Except: This guarantee does not apply to equality on maps, because th
 4393                // of maps is not restricted, only the Domain type.  However, the equality operator is checked above.)
 4394                case BinaryExpr.ResolvedOpcode.InSeq:
 4395                case BinaryExpr.ResolvedOpcode.NotInSeq:
 4396                case BinaryExpr.ResolvedOpcode.Prefix:
 4397                case BinaryExpr.ResolvedOpcode.ProperPrefix:
 504398                  if (!t1.SupportsEquality) {
 04399                    resolver.reporter.Error(MessageSource.Resolver, e.E1, "{0} can only be applied to expressions of seq
 504400                  } else if (!t0.SupportsEquality) {
 04401                    if (e.ResolvedOp == BinaryExpr.ResolvedOpcode.InSet || e.ResolvedOp == BinaryExpr.ResolvedOpcode.Not
 04402                      resolver.reporter.Error(MessageSource.Resolver, e.E0, "{0} can only be applied to expressions of t
 04403                    } else {
 04404                      resolver.reporter.Error(MessageSource.Resolver, e.E0, "{0} can only be applied to expressions of s
 04405                    }
 04406                  }
 504407                  break;
 4408                default:
 146144409                  break;
 4410              }
 146644411              break;
 4412          }
 6196794413        } else if (expr is ComprehensionExpr) {
 04414          var e = (ComprehensionExpr)expr;
 04415          foreach (var bv in e.BoundVars) {
 04416            VisitType(bv.tok, bv.Type, inGhostContext);
 04417          }
 5953934418        } else if (expr is LetExpr) {
 04419          var e = (LetExpr)expr;
 04420          Visit(Attributes.SubExpressions(e.Attributes), true);
 04421          if (e.Exact) {
 04422            Contract.Assert(e.LHSs.Count == e.RHSs.Count);
 04423            for (var i = 0; i < e.LHSs.Count; i++) {
 4424              // The VisitPattern function visits all BoundVar's in a pattern and returns
 4425              // "true" if all variables are ghost.
 04426              bool VisitPattern(CasePattern<BoundVar> pat, bool patternGhostContext) {
 04427                if (pat.Var != null) {
 04428                  VisitType(pat.tok, pat.Var.Type, patternGhostContext || pat.Var.IsGhost);
 04429                  return pat.Var.IsGhost;
 04430                } else {
 04431                  var allGhost = true;
 04432                  Contract.Assert(pat.Ctor != null);
 04433                  Contract.Assert(pat.Ctor.Formals.Count == pat.Arguments.Count);
 04434                  for (var i = 0; i < pat.Ctor.Formals.Count; i++) {
 04435                    var formal = pat.Ctor.Formals[i];
 04436                    var arg = pat.Arguments[i];
 4437                    // don't use short-circuit booleans in the following line, because we want to visit all nested patte
 04438                    allGhost &= VisitPattern(arg, patternGhostContext || formal.IsGhost);
 04439                  }
 04440                  return allGhost;
 4441                }
 04442              }
 4443
 04444              var allGhosts = VisitPattern(e.LHSs[i], inGhostContext);
 04445              Visit(e.RHSs[i], inGhostContext || allGhosts);
 04446            }
 04447          } else {
 04448            Contract.Assert(e.RHSs.Count == 1);
 04449            var allGhost = true;
 04450            foreach (var bv in e.BoundVars) {
 04451              if (!bv.IsGhost) {
 04452                allGhost = false;
 04453              }
 04454              VisitType(bv.tok, bv.Type, inGhostContext || bv.IsGhost);
 04455            }
 04456            Visit(e.RHSs[0], inGhostContext || allGhost);
 04457          }
 04458          Visit(e.Body, inGhostContext);
 04459          return false;
 6009134460        } else if (expr is MemberSelectExpr) {
 55204461          var e = (MemberSelectExpr)expr;
 55204462          if (e.Member is Function || e.Member is Method) {
 04463            CheckTypeInstantiation(e.tok, e.Member.WhatKind, e.Member.Name, ((ICallable)e.Member).TypeArgs, e.TypeApplic
 04464          }
 5953934465        } else if (expr is FunctionCallExpr) {
 04466          var e = (FunctionCallExpr)expr;
 04467          CheckTypeInstantiation(e.tok, e.Function.WhatKind, e.Function.Name, e.Function.TypeArgs, e.TypeApplication_Jus
 4468          // recursively visit all subexpressions (all actual parameters), noting which ones correspond to ghost formal 
 04469          Visit(e.Receiver, inGhostContext);
 04470          Contract.Assert(e.Args.Count == e.Function.Formals.Count);
 04471          for (var i = 0; i < e.Args.Count; i++) {
 04472            Visit(e.Args[i], inGhostContext || e.Function.Formals[i].IsGhost);
 04473          }
 04474          return false;  // we've done what there is to be done
 6009034475        } else if (expr is DatatypeValue) {
 110304476          var e = (DatatypeValue)expr;
 4477          // recursively visit all subexpressions (all actual parameters), noting which ones correspond to ghost formal 
 110304478          Contract.Assert(e.Arguments.Count == e.Ctor.Formals.Count);
 862304479          for (var i = 0; i < e.Arguments.Count; i++) {
 213904480            Visit(e.Arguments[i], inGhostContext || e.Ctor.Formals[i].IsGhost);
 213904481          }
 110304482          return false;  // we've done what there is to be done
 5788434483        } else if (expr is SetDisplayExpr || expr is MultiSetDisplayExpr || expr is MapDisplayExpr || expr is SeqConstru
 5992654484                   expr is MultiSetFormingExpr || expr is StaticReceiverExpr) {
 4485          // This catches other expressions whose type may potentially be illegal
 204224486          VisitType(expr.tok, expr.Type, inGhostContext);
 5788434487        } else if (expr is StmtExpr) {
 04488          var e = (StmtExpr)expr;
 04489          Visit(e.S, true);
 04490          Visit(e.E, inGhostContext);
 04491          return false;
 4492        }
 6086494493        return true;
 6196794494      }
 4495
 1727944496      public void VisitType(IToken tok, Type type, bool inGhostContext) {
 4497        Contract.Requires(tok != null);
 4498        Contract.Requires(type != null);
 1727944499        type = type.Normalize();  // we only do a .Normalize() here, because we want to keep stop at any type synonym or
 2775184500        if (type is BasicType) {
 4501          // fine
 1791084502        } else if (type is SetType) {
 63144503          var st = (SetType)type;
 63144504          var argType = st.Arg;
 63144505          if (!inGhostContext && !argType.SupportsEquality) {
 04506            resolver.reporter.Error(MessageSource.Resolver, tok, "{2}set argument type must support equality (got {0}){1
 04507          }
 63144508          VisitType(tok, argType, inGhostContext);
 4509
 724504510        } else if (type is MultiSetType) {
 43804511          var argType = ((MultiSetType)type).Arg;
 43804512          if (!inGhostContext && !argType.SupportsEquality) {
 04513            resolver.reporter.Error(MessageSource.Resolver, tok, "multiset argument type must support equality (got {0})
 4514
 04515          }
 43804516          VisitType(tok, argType, inGhostContext);
 784904517        } else if (type is MapType) {
 167344518          var mt = (MapType)type;
 167344519          if (!inGhostContext && !mt.Domain.SupportsEquality) {
 04520            resolver.reporter.Error(MessageSource.Resolver, tok, "{2}map domain type must support equality (got {0}){1}"
 04521          }
 167344522          VisitType(tok, mt.Domain, inGhostContext);
 167344523          VisitType(tok, mt.Range, inGhostContext);
 4524
 674504525        } else if (type is SeqType) {
 100744526          Type argType = ((SeqType)type).Arg;
 100744527          VisitType(tok, argType, inGhostContext);
 4528
 712104529        } else if (type is UserDefinedType) {
 305684530          var udt = (UserDefinedType)type;
 305684531          Contract.Assert(udt.ResolvedClass != null);
 305684532          var formalTypeArgs = udt.ResolvedClass.TypeArgs;
 305684533          Contract.Assert(formalTypeArgs != null);
 305684534          CheckTypeInstantiation(udt.tok, "type", udt.ResolvedClass.Name, formalTypeArgs, udt.TypeArgs, inGhostContext);
 4535
 305684536        } else if (type is TypeProxy) {
 4537          // the type was underconstrained; this is checked elsewhere, but it is not in violation of the equality-type t
 04538        } else {
 04539          Contract.Assert(false); throw new cce.UnreachableException();  // unexpected type
 4540        }
 1727944541      }
 4542
 337744543      void CheckTypeInstantiation(IToken tok, string what, string className, List<TypeParameter> formalTypeArgs, List<Ty
 4544        Contract.Requires(tok != null);
 4545        Contract.Requires(what != null);
 4546        Contract.Requires(className != null);
 4547        Contract.Requires(formalTypeArgs != null);
 4548        Contract.Requires(actualTypeArgs != null);
 4549        Contract.Requires(formalTypeArgs.Count == actualTypeArgs.Count);
 4550
 1891924551        for (var i = 0; i < formalTypeArgs.Count; i++) {
 405484552          var formal = formalTypeArgs[i];
 405484553          var actual = actualTypeArgs[i];
 405484554          if (!CheckCharacteristics(formal.Characteristics, actual, inGhostContext, out var whatIsWrong, out var hint)) 
 04555            resolver.reporter.Error(MessageSource.Resolver, tok, "type parameter{0} ({1}) passed to {2} {3} must support
 04556              actualTypeArgs.Count == 1 ? "" : " " + i, formal.Name, what, className, whatIsWrong, actual, hint);
 04557          }
 405484558          VisitType(tok, actual, inGhostContext);
 405484559        }
 337744560      }
 4561
 405484562      bool CheckCharacteristics(TypeParameter.TypeParameterCharacteristics formal, Type actual, bool inGhostContext, out
 4563        Contract.Ensures(Contract.Result<bool>() || (Contract.ValueAtReturn(out whatIsWrong) != null && Contract.ValueAt
 405484564        if (!inGhostContext && formal.EqualitySupport != TypeParameter.EqualitySupportValue.Unspecified && !actual.Suppo
 04565          whatIsWrong = "equality";
 04566          hint = TypeEqualityErrorMessageHint(actual);
 04567          return false;
 4568        }
 405484569        var cl = (actual.Normalize() as UserDefinedType)?.ResolvedClass;
 405484570        var tp = (TopLevelDecl)(cl as TypeParameter) ?? cl as AbstractTypeDecl;
 405484571        if (formal.HasCompiledValue && (inGhostContext ? !actual.IsNonempty : !actual.HasCompilableValue)) {
 04572          whatIsWrong = "auto-initialization";
 04573          hint = tp == null ? "" :
 04574            string.Format(" (perhaps try declaring {2} '{0}' on line {1} as '{0}(0)', which says it can only be instanti
 04575          return false;
 4576        }
 405484577        if (formal.IsNonempty && !actual.IsNonempty) {
 04578          whatIsWrong = "nonempty";
 04579          hint = tp == null ? "" :
 04580            string.Format(" (perhaps try declaring {2} '{0}' on line {1} as '{0}(00)', which says it can only be instant
 04581          return false;
 4582        }
 405484583        if (formal.ContainsNoReferenceTypes && actual.MayInvolveReferences) {
 04584          whatIsWrong = "no references";
 04585          hint = tp == null ? "" :
 04586            string.Format(" (perhaps try declaring {2} '{0}' on line {1} as '{0}(!new)', which says it can only be insta
 04587          return false;
 4588        }
 405484589        whatIsWrong = null;
 405484590        hint = null;
 405484591        return true;
 405484592      }
 4593
 04594      string TypeEqualityErrorMessageHint(Type argType) {
 4595        Contract.Requires(argType != null);
 04596        var cl = (argType.Normalize() as UserDefinedType)?.ResolvedClass;
 04597        var tp = (TopLevelDecl)(cl as TypeParameter) ?? cl as AbstractTypeDecl;
 04598        if (tp != null) {
 04599          return string.Format(" (perhaps try declaring {2} '{0}' on line {1} as '{0}(==)', which says it can only be in
 4600        }
 04601        return "";
 04602      }
 4603    }
 4604
 129454605    public static bool CanCompareWith(Expression expr) {
 4606      Contract.Requires(expr != null);
 258904607      if (expr.Type.SupportsEquality) {
 129454608        return true;
 4609      }
 04610      expr = expr.Resolved;
 04611      if (expr is DatatypeValue datatypeValue && !datatypeValue.Ctor.EnclosingDatatype.HasGhostVariant) {
 04612        for (var i = 0; i < datatypeValue.Ctor.Formals.Count; i++) {
 04613          if (datatypeValue.Ctor.Formals[i].IsGhost) {
 04614            return false;
 04615          } else if (!CanCompareWith(datatypeValue.Arguments[i])) {
 04616            return false;
 4617          }
 04618        }
 04619        return true;
 04620      } else if (expr is DisplayExpression) {
 04621        var e = (DisplayExpression)expr;
 04622        return e.Elements.Count == 0;
 04623      } else if (expr is MapDisplayExpr) {
 04624        var e = (MapDisplayExpr)expr;
 04625        return e.Elements.Count == 0;
 4626      }
 04627      return false;
 129454628    }
 4629
 4630    #endregion CheckTypeCharacteristics
 4631
 4632    // ------------------------------------------------------------------------------------------------------
 4633    // ----- ComputeGhostInterest ---------------------------------------------------------------------------
 4634    // ------------------------------------------------------------------------------------------------------
 4635    #region ComputeGhostInterest
 18844636    public void ComputeGhostInterest(Statement stmt, bool mustBeErasable, [CanBeNull] string proofContext, ICodeContext 
 4637      Contract.Requires(stmt != null);
 4638      Contract.Requires(codeContext != null);
 18844639      var visitor = new GhostInterestVisitor(codeContext, this, reporter, false, codeContext is Method);
 18844640      visitor.Visit(stmt, mustBeErasable, proofContext);
 18844641    }
 4642
 4643    #endregion
 4644
 4645    // ------------------------------------------------------------------------------------------------------
 4646    // ----- FillInDefaultLoopDecreases ---------------------------------------------------------------------
 4647    // ------------------------------------------------------------------------------------------------------
 4648    #region FillInDefaultLoopDecreases
 4649    class FillInDefaultLoopDecreases_Visitor : ResolverBottomUpVisitor {
 4650      readonly ICallable EnclosingMethod;
 4651      public FillInDefaultLoopDecreases_Visitor(Resolver resolver, ICallable enclosingMethod)
 18844652        : base(resolver) {
 4653        Contract.Requires(resolver != null);
 4654        Contract.Requires(enclosingMethod != null);
 9424655        EnclosingMethod = enclosingMethod;
 9424656      }
 788114657      protected override void VisitOneStmt(Statement stmt) {
 789864658        if (stmt is WhileStmt) {
 1754659          var s = (WhileStmt)stmt;
 1754660          resolver.FillInDefaultLoopDecreases(s, s.Guard, s.Decreases.Expressions, EnclosingMethod);
 788114661        } else if (stmt is AlternativeLoopStmt) {
 04662          var s = (AlternativeLoopStmt)stmt;
 04663          resolver.FillInDefaultLoopDecreases(s, null, s.Decreases.Expressions, EnclosingMethod);
 04664        }
 788114665      }
 4666    }
 4667    #endregion FillInDefaultLoopDecreases
 4668
 4669    // ------------------------------------------------------------------------------------------------------
 4670    // ----- ReportMoreAdditionalInformation ----------------------------------------------------------------
 4671    // ------------------------------------------------------------------------------------------------------
 4672    #region ReportOtherAdditionalInformation_Visitor
 4673    class ReportOtherAdditionalInformation_Visitor : ResolverBottomUpVisitor {
 4674      public ReportOtherAdditionalInformation_Visitor(Resolver resolver)
 18844675        : base(resolver) {
 4676        Contract.Requires(resolver != null);
 9424677      }
 788114678      protected override void VisitOneStmt(Statement stmt) {
 788114679        if (stmt is ForallStmt) {
 04680          var s = (ForallStmt)stmt;
 04681          if (s.Kind == ForallStmt.BodyKind.Call) {
 04682            var cs = (CallStmt)s.S0;
 4683            // show the callee's postcondition as the postcondition of the 'forall' statement
 4684            // TODO:  The following substitutions do not correctly take into consideration variable capture; hence, what
 04685            var argsSubstMap = new Dictionary<IVariable, Expression>();  // maps formal arguments to actuals
 04686            Contract.Assert(cs.Method.Ins.Count == cs.Args.Count);
 04687            for (int i = 0; i < cs.Method.Ins.Count; i++) {
 04688              argsSubstMap.Add(cs.Method.Ins[i], cs.Args[i]);
 04689            }
 04690            var substituter = new AlphaConvertingSubstituter(cs.Receiver, argsSubstMap, new Dictionary<TypeParameter, Ty
 04691            if (!Attributes.Contains(s.Attributes, "auto_generated")) {
 04692              foreach (var ens in cs.Method.Ens) {
 04693                var p = substituter.Substitute(ens.E);  // substitute the call's actuals for the method's formals
 04694                resolver.reporter.Info(MessageSource.Resolver, s.Tok, "ensures " + Printer.ExprToString(resolver.Options
 04695              }
 04696            }
 04697          }
 04698        }
 788114699      }
 4700    }
 4701    #endregion ReportOtherAdditionalInformation_Visitor
 4702
 4703    // ------------------------------------------------------------------------------------------------------
 4704    // ----- ReportMoreAdditionalInformation ----------------------------------------------------------------
 4705    // ------------------------------------------------------------------------------------------------------
 4706    #region CheckDividedConstructorInit
 4707    class CheckDividedConstructorInit_Visitor : ResolverTopDownVisitor<int> {
 4708      public CheckDividedConstructorInit_Visitor(Resolver resolver)
 6324709        : base(resolver) {
 4710        Contract.Requires(resolver != null);
 3164711      }
 04712      public void CheckInit(List<Statement> initStmts) {
 4713        Contract.Requires(initStmts != null);
 04714        initStmts.Iter(CheckInit);
 04715      }
 4716      /// <summary>
 4717      /// This method almost does what Visit(Statement) does, except that it handles assignments to
 4718      /// fields differently.
 4719      /// </summary>
 04720      void CheckInit(Statement stmt) {
 4721        Contract.Requires(stmt != null);
 4722        // Visit(stmt) would do:
 4723        //     stmt.SubExpressions.Iter(Visit);    (*)
 4724        //     stmt.SubStatements.Iter(Visit);     (**)
 4725        //     VisitOneStmt(stmt);                 (***)
 4726        // We may do less for (*), we always use CheckInit instead of Visit in (**), and we do (***) the same.
 04727        if (stmt is AssignStmt) {
 04728          var s = stmt as AssignStmt;
 4729          // The usual visitation of s.SubExpressions.Iter(Visit) would do the following:
 4730          //   Attributes.SubExpressions(s.Attributes).Iter(Visit);  (+)
 4731          //   Visit(s.Lhs);                                         (++)
 4732          //   s.Rhs.SubExpressions.Iter(Visit);                     (+++)
 4733          // Here, we may do less; in particular, we may omit (++).
 04734          Attributes.SubExpressions(s.Attributes).Iter(VisitExpr);  // (+)
 04735          var mse = s.Lhs as MemberSelectExpr;
 04736          if (mse != null && Expression.AsThis(mse.Obj) != null) {
 04737            if (s.Rhs is ExprRhs) {
 4738              // This is a special case we allow.  Omit s.Lhs in the recursive visits.  That is, we omit (++).
 4739              // Furthermore, because the assignment goes to a field of "this" and won't be available until after
 4740              // the "new;", we can allow certain specific (and useful) uses of "this" in the RHS.
 04741              s.Rhs.SubExpressions.Iter(LiberalRHSVisit);  // (+++)
 04742            } else {
 04743              s.Rhs.SubExpressions.Iter(VisitExpr);  // (+++)
 04744            }
 04745          } else {
 04746            VisitExpr(s.Lhs);  // (++)
 04747            s.Rhs.SubExpressions.Iter(VisitExpr);  // (+++)
 04748          }
 04749        } else {
 04750          stmt.SubExpressions.Iter(VisitExpr);  // (*)
 04751        }
 04752        stmt.SubStatements.Iter(CheckInit);  // (**)
 04753        int dummy = 0;
 04754        VisitOneStmt(stmt, ref dummy);  // (***)
 04755      }
 04756      void VisitExpr(Expression expr) {
 4757        Contract.Requires(expr != null);
 04758        Visit(expr, 0);
 04759      }
 04760      protected override bool VisitOneExpr(Expression expr, ref int unused) {
 04761        if (expr is MemberSelectExpr) {
 04762          var e = (MemberSelectExpr)expr;
 04763          if (e.Member.IsInstanceIndependentConstant && Expression.AsThis(e.Obj) != null) {
 04764            return false;  // don't continue the recursion
 4765          }
 04766        } else if (expr is ThisExpr && !(expr is ImplicitThisExpr_ConstructorCall)) {
 04767          resolver.reporter.Error(MessageSource.Resolver, expr.tok, "in the first division of the constructor body (befo
 04768        }
 04769        return base.VisitOneExpr(expr, ref unused);
 04770      }
 04771      void LiberalRHSVisit(Expression expr) {
 4772        Contract.Requires(expr != null);
 4773        // It is important not to allow "this" to flow into something that can be used (for compilation or
 4774        // verification purposes) before the "new;", because, to the verifier, "this" has not yet been allocated.
 4775        // The verifier is told that everything reachable from the heap is expected to be allocated and satisfy all
 4776        // the usual properties, so "this" had better not become reachable from the heap until after the "new;"
 4777        // that does the actual allocation of "this".
 4778        // Within these restrictions, we can allow the (not yet fully available) value "this" to flow into values
 4779        // stored in fields of "this".  Such values are naked occurrences of "this" and "this" occurring
 4780        // as part of constructing a value type.  Since by this rule, "this" may be part of the value stored in
 4781        // a field of "this", we must apply the same rules to uses of the values of fields of "this".
 04782        if (expr is ConcreteSyntaxExpression) {
 04783        } else if (expr is ThisExpr) {
 04784        } else if (expr is MemberSelectExpr && IsThisDotField((MemberSelectExpr)expr)) {
 04785        } else if (expr is SetDisplayExpr) {
 04786        } else if (expr is MultiSetDisplayExpr) {
 04787        } else if (expr is SeqDisplayExpr) {
 04788        } else if (expr is MapDisplayExpr) {
 04789        } else if (expr is BinaryExpr && IsCollectionOperator(((BinaryExpr)expr).ResolvedOp)) {
 04790        } else if (expr is DatatypeValue) {
 04791        } else if (expr is ITEExpr) {
 04792          var e = (ITEExpr)expr;
 04793          VisitExpr(e.Test);
 04794          LiberalRHSVisit(e.Thn);
 04795          LiberalRHSVisit(e.Els);
 04796          return;
 04797        } else {
 4798          // defer to the usual Visit
 04799          VisitExpr(expr);
 04800          return;
 4801        }
 04802        expr.SubExpressions.Iter(LiberalRHSVisit);
 04803      }
 04804      static bool IsThisDotField(MemberSelectExpr expr) {
 4805        Contract.Requires(expr != null);
 04806        return Expression.AsThis(expr.Obj) != null && expr.Member is Field;
 04807      }
 04808      static bool IsCollectionOperator(BinaryExpr.ResolvedOpcode op) {
 04809        switch (op) {
 4810          // sets:  +, *, -
 4811          case BinaryExpr.ResolvedOpcode.Union:
 4812          case BinaryExpr.ResolvedOpcode.Intersection:
 4813          case BinaryExpr.ResolvedOpcode.SetDifference:
 4814          // multisets: +, *, -
 4815          case BinaryExpr.ResolvedOpcode.MultiSetUnion:
 4816          case BinaryExpr.ResolvedOpcode.MultiSetIntersection:
 4817          case BinaryExpr.ResolvedOpcode.MultiSetDifference:
 4818          // sequences: +
 4819          case BinaryExpr.ResolvedOpcode.Concat:
 4820          // maps: +, -
 4821          case BinaryExpr.ResolvedOpcode.MapMerge:
 4822          case BinaryExpr.ResolvedOpcode.MapSubtraction:
 04823            return true;
 4824          default:
 04825            return false;
 4826        }
 04827      }
 4828    }
 4829    #endregion
 4830
 4831    // ------------------------------------------------------------------------------------------------------
 4832    // ------------------------------------------------------------------------------------------------------
 4833    // ------------------------------------------------------------------------------------------------------
 4834
 27844835    bool InferRequiredEqualitySupport(TypeParameter tp, Type type) {
 4836      Contract.Requires(tp != null);
 4837      Contract.Requires(type != null);
 4838
 27844839      type = type.Normalize();  // we only do a .Normalize() here, because we want to keep stop at any type synonym or s
 40584840      if (type is BasicType) {
 27844841      } else if (type is SetType) {
 04842        var st = (SetType)type;
 04843        return st.Arg.AsTypeParameter == tp || InferRequiredEqualitySupport(tp, st.Arg);
 15204844      } else if (type is MultiSetType) {
 104845        var ms = (MultiSetType)type;
 104846        return ms.Arg.AsTypeParameter == tp || InferRequiredEqualitySupport(tp, ms.Arg);
 15004847      } else if (type is MapType) {
 04848        var mt = (MapType)type;
 04849        return mt.Domain.AsTypeParameter == tp || InferRequiredEqualitySupport(tp, mt.Domain) || InferRequiredEqualitySu
 19084850      } else if (type is SeqType) {
 4084851        var sq = (SeqType)type;
 4084852        return InferRequiredEqualitySupport(tp, sq.Arg);
 21844853      } else if (type is UserDefinedType) {
 10924854        var udt = (UserDefinedType)type;
 10924855        List<TypeParameter> formalTypeArgs = udt.ResolvedClass.TypeArgs;
 10924856        Contract.Assert(formalTypeArgs != null);
 10924857        Contract.Assert(formalTypeArgs.Count == udt.TypeArgs.Count);
 10924858        var i = 0;
 36124859        foreach (var argType in udt.TypeArgs) {
 1124860          var formalTypeArg = formalTypeArgs[i];
 1124861          if ((formalTypeArg.SupportsEquality && argType.AsTypeParameter == tp) || InferRequiredEqualitySupport(tp, argT
 04862            return true;
 4863          }
 1124864          i++;
 1124865        }
 10924866        if (udt.ResolvedClass is TypeSynonymDecl) {
 04867          var syn = (TypeSynonymDecl)udt.ResolvedClass;
 04868          if (syn.IsRevealedInScope(Type.GetScope())) {
 04869            return InferRequiredEqualitySupport(tp, syn.RhsWithArgument(udt.TypeArgs));
 4870          }
 04871        }
 10924872      } else {
 04873        Contract.Assert(false); throw new cce.UnreachableException();  // unexpected type
 4874      }
 23664875      return false;
 27844876    }
 4877
 4878    TopLevelDeclWithMembers currentClass;
 4879    public Method currentMethod;
 4880    readonly Scope<TypeParameter>/*!*/ allTypeParameters;
 4881    public readonly Scope<IVariable>/*!*/ scope;
 4882    Scope<Statement>/*!*/ enclosingStatementLabels;
 4883    public readonly Scope<Label>/*!*/ DominatingStatementLabels;
 1124884    List<Statement> loopStack = new List<Statement>();  // the enclosing loops (from which it is possible to break out)
 4885
 4886    /// <summary>
 4887    /// Resolves the types along .ParentTraits and fills in .ParentTraitHeads
 4888    /// </summary>
 4834889    void ResolveParentTraitTypes(TopLevelDeclWithMembers cl, Graph<TopLevelDeclWithMembers> parentRelation) {
 4890      Contract.Requires(cl != null);
 4891      Contract.Requires(currentClass == null);
 4892      Contract.Ensures(currentClass == null);
 4893
 4834894      currentClass = cl;
 4834895      allTypeParameters.PushMarker();
 4834896      ResolveTypeParameters(cl.TypeArgs, false, cl);
 14494897      foreach (var tt in cl.ParentTraits) {
 04898        var prevErrorCount = reporter.Count(ErrorLevel.Error);
 04899        ResolveType(cl.tok, tt, new NoContext(cl.EnclosingModuleDefinition), ResolveTypeOptionEnum.DontInfer, null);
 04900        if (prevErrorCount == reporter.Count(ErrorLevel.Error)) {
 04901          var udt = tt as UserDefinedType;
 04902          if (udt != null && udt.ResolvedClass is NonNullTypeDecl nntd && nntd.ViewAsClass is TraitDecl trait) {
 4903            // disallowing inheritance in multi module case
 04904            bool termination = true;
 04905            if (cl.EnclosingModuleDefinition == trait.EnclosingModuleDefinition || trait.IsObjectTrait || (Attributes.Co
 4906              // all is good (or the user takes responsibility for the lack of termination checking)
 04907              if (!cl.ParentTraitHeads.Contains(trait)) {
 04908                cl.ParentTraitHeads.Add(trait);
 04909                parentRelation.AddEdge(cl, trait);
 04910              }
 04911            } else {
 04912              reporter.Error(MessageSource.Resolver, udt.tok, "{0} '{1}' is in a different module than trait '{2}'. A {0
 04913            }
 04914          } else {
 04915            reporter.Error(MessageSource.Resolver, udt != null ? udt.tok : cl.tok, "a {0} can only extend traits (found 
 04916          }
 04917        }
 04918      }
 4834919      allTypeParameters.PopMarker();
 4834920      currentClass = null;
 4834921    }
 4922
 4923    /// <summary>
 4924    /// This method idempotently fills in .InheritanceInformation, .ParentFormalTypeParametersToActuals, and the
 4925    /// name->MemberDecl table for "cl" and the transitive parent traits of "cl". It also checks that every (transitive)
 4926    /// parent trait is instantiated with the same type parameters
 4927    /// The method assumes that all types along .ParentTraits have been successfully resolved and .ParentTraitHeads been
 4928    /// </summary>
 4834929    void RegisterInheritedMembers(TopLevelDeclWithMembers cl) {
 4930      Contract.Requires(cl != null);
 4931
 4834932      if (cl.ParentTypeInformation != null) {
 04933        return;
 4934      }
 4834935      cl.ParentTypeInformation = new TopLevelDeclWithMembers.InheritanceInformationClass();
 4936
 4937      // populate .ParentTypeInformation and .ParentFormalTypeParametersToActuals for the immediate parent traits
 14494938      foreach (var tt in cl.ParentTraits) {
 04939        var udt = (UserDefinedType)tt;
 04940        var nntd = (NonNullTypeDecl)udt.ResolvedClass;
 04941        var trait = (TraitDecl)nntd.ViewAsClass;
 04942        cl.ParentTypeInformation.Record(trait, udt);
 04943        Contract.Assert(trait.TypeArgs.Count == udt.TypeArgs.Count);
 04944        for (var i = 0; i < trait.TypeArgs.Count; i++) {
 4945          // there may be duplciate parent traits, which haven't been checked for yet, so add mapping only for the first
 04946          if (!cl.ParentFormalTypeParametersToActuals.ContainsKey(trait.TypeArgs[i])) {
 04947            cl.ParentFormalTypeParametersToActuals.Add(trait.TypeArgs[i], udt.TypeArgs[i]);
 04948          }
 04949        }
 04950      }
 4951
 4952      // populate .ParentTypeInformation and .ParentFormalTypeParametersToActuals for the transitive parent traits
 14494953      foreach (var trait in cl.ParentTraitHeads) {
 4954        // make sure the parent trait has been processed; then, incorporate its inheritance information
 04955        RegisterInheritedMembers(trait);
 04956        cl.ParentTypeInformation.Extend(trait, trait.ParentTypeInformation, cl.ParentFormalTypeParametersToActuals);
 04957        foreach (var entry in trait.ParentFormalTypeParametersToActuals) {
 04958          var v = entry.Value.Subst(cl.ParentFormalTypeParametersToActuals);
 04959          if (!cl.ParentFormalTypeParametersToActuals.ContainsKey(entry.Key)) {
 04960            cl.ParentFormalTypeParametersToActuals.Add(entry.Key, v);
 04961          }
 04962        }
 04963      }
 4964
 4965      // Check that every (transitive) parent trait is instantiated with the same type parameters
 14494966      foreach (var group in cl.ParentTypeInformation.GetTypeInstantiationGroups()) {
 04967        Contract.Assert(1 <= group.Count);
 04968        var ty = group[0].Item1;
 04969        for (var i = 1; i < group.Count; i++) {
 04970          if (!group.GetRange(0, i).Exists(pair => pair.Item1.Equals(group[i].Item1))) {
 04971            var via0 = group[0].Item2.Count == 0 ? "" : " (via " + Util.Comma(group[0].Item2, traitDecl => traitDecl.Nam
 04972            var via1 = group[i].Item2.Count == 0 ? "" : " (via " + Util.Comma(group[i].Item2, traitDecl => traitDecl.Nam
 04973            reporter.Error(MessageSource.Resolver, cl.tok,
 04974              "duplicate trait parents with the same head type must also have the same type arguments; got {0}{1} and {2
 04975              ty, via0, group[i].Item1, via1);
 04976          }
 04977        }
 04978      }
 4979
 4980      // Update the name->MemberDecl table for the class. Report an error if the same name refers to more than one membe
 4981      // except when such duplication is purely that one member, say X, is inherited and the other is an override of X.
 4834982      var inheritedMembers = new Dictionary<string, MemberDecl>();
 14494983      foreach (var trait in cl.ParentTraitHeads) {
 04984        foreach (var traitMember in classMembers[trait].Values) {  // TODO: rather than using .Values, it would be nice 
 04985          if (!inheritedMembers.TryGetValue(traitMember.Name, out var prevMember)) {
 4986            // record "traitMember" as an inherited member
 04987            inheritedMembers.Add(traitMember.Name, traitMember);
 04988          } else if (traitMember == prevMember) {
 4989            // same member, inherited two different ways
 04990          } else if (traitMember.Overrides(prevMember)) {
 4991            // we're inheriting "prevMember" and "traitMember" from different parent traits, where "traitMember" is an o
 04992            Contract.Assert(traitMember.EnclosingClass != cl && prevMember.EnclosingClass != cl && traitMember.Enclosing
 4993            // re-map "traitMember.Name" to point to the overriding member
 04994            inheritedMembers[traitMember.Name] = traitMember;
 04995          } else if (prevMember.Overrides(traitMember)) {
 4996            // we're inheriting "prevMember" and "traitMember" from different parent traits, where "prevMember" is an ov
 04997            Contract.Assert(traitMember.EnclosingClass != cl && prevMember.EnclosingClass != cl && traitMember.Enclosing
 4998            // keep the mapping to "prevMember"
 04999          } else {
 5000            // "prevMember" and "traitMember" refer to different members (with the same name)
 05001            reporter.Error(MessageSource.Resolver, cl.tok, "{0} '{1}' inherits a member named '{2}' from both traits '{3
 05002              cl.WhatKind, cl.Name, traitMember.Name, prevMember.EnclosingClass.Name, traitMember.EnclosingClass.Name);
 05003          }
 05004        }
 05005      }
 5006      // Incorporate the inherited members into the name->MemberDecl mapping of "cl"
 4835007      var members = classMembers[cl];
 14495008      foreach (var entry in inheritedMembers) {
 05009        var name = entry.Key;
 05010        var traitMember = entry.Value;
 05011        if (!members.TryGetValue(name, out var clMember)) {
 05012          members.Add(name, traitMember);
 05013        } else {
 05014          Contract.Assert(clMember.EnclosingClass == cl);  // sanity check
 05015          Contract.Assert(clMember.OverriddenMember == null);  // sanity check
 05016          clMember.OverriddenMember = traitMember;
 05017        }
 05018      }
 4835019    }
 5020
 5021    /// <summary>
 5022    /// Assumes type parameters have already been pushed
 5023    /// </summary>
 4835024    void ResolveClassMemberTypes(TopLevelDeclWithMembers cl) {
 5025      Contract.Requires(cl != null);
 5026      Contract.Requires(currentClass == null);
 5027      Contract.Ensures(currentClass == null);
 4835028      currentClass = cl;
 5029
 75965030      foreach (MemberDecl member in cl.Members) {
 20495031        member.EnclosingClass = cl;
 20495032        if (member is Field) {
 05033          if (member is ConstantField) {
 05034            var m = (ConstantField)member;
 05035            ResolveType(member.tok, ((Field)member).Type, m, ResolveTypeOptionEnum.DontInfer, null);
 05036          } else {
 5037            // In the following, we pass in a NoContext, because any cycle formed by a redirecting-type constraints woul
 5038            // dereference the heap, and such constraints are not allowed to dereference the heap so an error will be pr
 5039            // even if we don't detect this cycle.
 05040            ResolveType(member.tok, ((Field)member).Type, new NoContext(cl.EnclosingModuleDefinition), ResolveTypeOption
 05041          }
 20495042        } else if (member is Function) {
 05043          var f = (Function)member;
 05044          var ec = reporter.Count(ErrorLevel.Error);
 05045          allTypeParameters.PushMarker();
 05046          ResolveTypeParameters(f.TypeArgs, true, f);
 05047          ResolveFunctionSignature(f);
 05048          allTypeParameters.PopMarker();
 05049          if (f is ExtremePredicate && ec == reporter.Count(ErrorLevel.Error)) {
 05050            var ff = ((ExtremePredicate)f).PrefixPredicate;  // note, may be null if there was an error before the prefi
 05051            if (ff != null) {
 05052              ff.EnclosingClass = cl;
 05053              allTypeParameters.PushMarker();
 05054              ResolveTypeParameters(ff.TypeArgs, true, ff);
 05055              ResolveFunctionSignature(ff);
 05056              allTypeParameters.PopMarker();
 05057            }
 05058          }
 05059          if (f.ByMethodDecl != null) {
 05060            f.ByMethodDecl.EnclosingClass = cl;
 05061          }
 5062
 40985063        } else if (member is Method) {
 20495064          var m = (Method)member;
 20495065          var ec = reporter.Count(ErrorLevel.Error);
 20495066          allTypeParameters.PushMarker();
 20495067          ResolveTypeParameters(m.TypeArgs, true, m);
 20495068          ResolveMethodSignature(m);
 20495069          allTypeParameters.PopMarker();
 20495070          if (m is ExtremeLemma com && com.PrefixLemma != null && ec == reporter.Count(ErrorLevel.Error)) {
 05071            var mm = com.PrefixLemma;
 5072            // resolve signature of the prefix lemma
 05073            mm.EnclosingClass = cl;
 05074            allTypeParameters.PushMarker();
 05075            ResolveTypeParameters(mm.TypeArgs, true, mm);
 05076            ResolveMethodSignature(mm);
 05077            allTypeParameters.PopMarker();
 05078          }
 5079
 20495080        } else {
 05081          Contract.Assert(false); throw new cce.UnreachableException();  // unexpected member type
 5082        }
 20495083      }
 5084
 4835085      currentClass = null;
 4835086    }
 5087
 5088    /// <summary>
 5089    /// This method checks the rules for inherited and overridden members. It also populates .InheritedMembers with the
 5090    /// non-static members that are inherited from parent traits.
 5091    /// </summary>
 4835092    void InheritedTraitMembers(TopLevelDeclWithMembers cl) {
 5093      Contract.Requires(cl != null);
 5094      Contract.Requires(cl.ParentTypeInformation != null);
 5095
 111485096      foreach (var member in classMembers[cl].Values) {
 32335097        if (member is PrefixPredicate || member is PrefixLemma) {
 5098          // these are handled with the corresponding extreme predicate/lemma
 05099          continue;
 5100        }
 32335101        if (member.EnclosingClass != cl) {
 5102          // The member is the one inherited from a trait (and the class does not itself define a member with this name)
 5103          // is fine for fields and for functions and methods with bodies. However, if "cl" is not itself a trait, then 
 5104          // or method, "cl" is required to at least redeclare the member with its signature.  (It should also provide a
 5105          // but that will be checked by the verifier.  And it should also have a body, but that will be checked by the 
 05106          if (member.IsStatic) {
 5107            // nothing to do
 05108          } else {
 05109            cl.InheritedMembers.Add(member);
 05110            if (member is Field || (member as Function)?.Body != null || (member as Method)?.Body != null) {
 5111              // member is a field or a fully defined function or method
 05112            } else if (cl is TraitDecl) {
 5113              // there are no expectations that a field needs to repeat the signature of inherited body-less members
 05114            } else if (Attributes.Contains(member.Attributes, "extern")) {
 5115              // Extern functions do not need to be reimplemented.
 5116              // TODO: When `:extern` is separated from `:compile false`, this should become `:compile false`.
 05117            } else if (member is Lemma && Attributes.Contains(member.Attributes, "opaque_reveal")) {
 5118              // reveal lemmas do not need to be reimplemented
 05119            } else {
 05120              reporter.Error(MessageSource.Resolver, cl.tok, "{0} '{1}' does not implement trait {2} '{3}.{4}'", cl.What
 05121            }
 05122          }
 05123          continue;
 5124        }
 64665125        if (member.OverriddenMember == null) {
 5126          // this member has nothing to do with the parent traits
 32335127          continue;
 5128        }
 5129
 05130        var traitMember = member.OverriddenMember;
 05131        var trait = traitMember.EnclosingClass;
 05132        if (traitMember.IsStatic) {
 05133          reporter.Error(MessageSource.Resolver, member.tok, "static {0} '{1}' is inherited from trait '{2}' and is not 
 05134            traitMember.WhatKind, traitMember.Name, trait.Name);
 05135        } else if (member.IsStatic) {
 05136          reporter.Error(MessageSource.Resolver, member.tok, "static member '{0}' overrides non-static member in trait '
 05137        } else if (traitMember is Field) {
 5138          // The class is not allowed to do anything with the field other than silently inherit it.
 05139          reporter.Error(MessageSource.Resolver, member.tok, "{0} '{1}' is inherited from trait '{2}' and is not allowed
 05140        } else if ((traitMember as Function)?.Body != null || (traitMember as Method)?.Body != null) {
 5141          // the overridden member is a fully defined function or method, so the class is not allowed to do anything wit
 05142          reporter.Error(MessageSource.Resolver, member.tok, "fully defined {0} '{1}' is inherited from trait '{2}' and 
 05143            traitMember.WhatKind, traitMember.Name, trait.Name);
 05144        } else if (member is Method != traitMember is Method ||
 05145                   member is Lemma != traitMember is Lemma ||
 05146                   member is TwoStateLemma != traitMember is TwoStateLemma ||
 05147                   member is LeastLemma != traitMember is LeastLemma ||
 05148                   member is GreatestLemma != traitMember is GreatestLemma ||
 05149                   member is Function != traitMember is Function ||
 05150                   member is TwoStateFunction != traitMember is TwoStateFunction ||
 05151                   member is LeastPredicate != traitMember is LeastPredicate ||
 05152                   member is GreatestPredicate != traitMember is GreatestPredicate) {
 05153          reporter.Error(MessageSource.Resolver, member.tok, "{0} '{1}' in '{2}' can only be overridden by a {0} (got {3
 05154        } else if (member.IsGhost != traitMember.IsGhost) {
 05155          reporter.Error(MessageSource.Resolver, member.tok, "overridden {0} '{1}' in '{2}' has different ghost/compiled
 05156            traitMember.WhatKind, traitMember.Name, cl.Name, trait.Name);
 05157        } else {
 5158          // Copy trait member's extern attribute onto class member if class does not provide one
 05159          if (!Attributes.Contains(member.Attributes, "extern") && Attributes.Contains(traitMember.Attributes, "extern")
 05160            var traitExternArgs = Attributes.FindExpressions(traitMember.Attributes, "extern");
 05161            member.Attributes = new Attributes("extern", traitExternArgs, member.Attributes);
 05162          }
 5163
 05164          if (traitMember is Method) {
 05165            var classMethod = (Method)member;
 05166            var traitMethod = (Method)traitMember;
 05167            classMethod.OverriddenMethod = traitMethod;
 5168
 05169            CheckOverride_MethodParameters(classMethod, traitMethod, cl.ParentFormalTypeParametersToActuals);
 5170
 05171            var traitMethodAllowsNonTermination = Contract.Exists(traitMethod.Decreases.Expressions, e => e is WildcardE
 05172            var classMethodAllowsNonTermination = Contract.Exists(classMethod.Decreases.Expressions, e => e is WildcardE
 05173            if (classMethodAllowsNonTermination && !traitMethodAllowsNonTermination) {
 05174              reporter.Error(MessageSource.Resolver, classMethod.tok, "not allowed to override a terminating method with
 05175            }
 5176
 05177          } else if (traitMember is Function) {
 05178            var classFunction = (Function)member;
 05179            var traitFunction = (Function)traitMember;
 05180            classFunction.OverriddenFunction = traitFunction;
 5181
 05182            CheckOverride_FunctionParameters(classFunction, traitFunction, cl.ParentFormalTypeParametersToActuals);
 5183
 05184          } else {
 05185            Contract.Assert(false); // unexpected member
 05186          }
 05187        }
 05188      }
 4835189    }
 5190
 05191    public void CheckOverride_FunctionParameters(Function nw, Function old, Dictionary<TypeParameter, Type> classTypeMap
 5192      Contract.Requires(nw != null);
 5193      Contract.Requires(old != null);
 5194      Contract.Requires(classTypeMap != null);
 5195
 05196      var typeMap = CheckOverride_TypeParameters(nw.tok, old.TypeArgs, nw.TypeArgs, nw.Name, "function", classTypeMap);
 05197      if (nw is ExtremePredicate nwFix && old is ExtremePredicate oldFix && nwFix.KNat != oldFix.KNat) {
 05198        reporter.Error(MessageSource.Resolver, nw,
 05199          "the type of special parameter '_k' of {0} '{1}' ({2}) must be the same as in the overridden {0} ({3})",
 05200          nw.WhatKind, nw.Name, nwFix.KNat ? "nat" : "ORDINAL", oldFix.KNat ? "nat" : "ORDINAL");
 05201      }
 05202      CheckOverride_ResolvedParameters(nw.tok, old.Formals, nw.Formals, nw.Name, "function", "parameter", typeMap);
 05203      var oldResultType = old.ResultType.Subst(typeMap);
 05204      if (!nw.ResultType.Equals(oldResultType, true)) {
 05205        reporter.Error(MessageSource.Resolver, nw, "the result type of function '{0}' ({1}) differs from that in the ove
 05206          nw.Name, nw.ResultType, oldResultType);
 05207      }
 05208    }
 5209
 05210    public void CheckOverride_MethodParameters(Method nw, Method old, Dictionary<TypeParameter, Type> classTypeMap) {
 5211      Contract.Requires(nw != null);
 5212      Contract.Requires(old != null);
 5213      Contract.Requires(classTypeMap != null);
 05214      var typeMap = CheckOverride_TypeParameters(nw.tok, old.TypeArgs, nw.TypeArgs, nw.Name, "method", classTypeMap);
 05215      if (nw is ExtremeLemma nwFix && old is ExtremeLemma oldFix && nwFix.KNat != oldFix.KNat) {
 05216        reporter.Error(MessageSource.Resolver, nw,
 05217          "the type of special parameter '_k' of {0} '{1}' ({2}) must be the same as in the overridden {0} ({3})",
 05218          nw.WhatKind, nw.Name, nwFix.KNat ? "nat" : "ORDINAL", oldFix.KNat ? "nat" : "ORDINAL");
 05219      }
 05220      CheckOverride_ResolvedParameters(nw.tok, old.Ins, nw.Ins, nw.Name, "method", "in-parameter", typeMap);
 05221      CheckOverride_ResolvedParameters(nw.tok, old.Outs, nw.Outs, nw.Name, "method", "out-parameter", typeMap);
 05222    }
 5223
 05224    private Dictionary<TypeParameter, Type> CheckOverride_TypeParameters(IToken tok, List<TypeParameter> old, List<TypeP
 5225      Contract.Requires(tok != null);
 5226      Contract.Requires(old != null);
 5227      Contract.Requires(nw != null);
 5228      Contract.Requires(name != null);
 5229      Contract.Requires(thing != null);
 05230      var typeMap = old.Count == 0 ? classTypeMap : new Dictionary<TypeParameter, Type>(classTypeMap);
 05231      if (old.Count != nw.Count) {
 05232        reporter.Error(MessageSource.Resolver, tok,
 05233          "{0} '{1}' is declared with a different number of type parameters ({2} instead of {3}) than in the overridden 
 05234      } else {
 05235        for (int i = 0; i < old.Count; i++) {
 05236          var o = old[i];
 05237          var n = nw[i];
 05238          typeMap.Add(o, new UserDefinedType(tok, n));
 5239          // Check type characteristics
 05240          if (o.Characteristics.EqualitySupport != TypeParameter.EqualitySupportValue.InferredRequired && o.Characterist
 05241            reporter.Error(MessageSource.Resolver, n.tok, "type parameter '{0}' is not allowed to change the requirement
 05242          }
 05243          if (o.Characteristics.HasCompiledValue != n.Characteristics.HasCompiledValue) {
 05244            reporter.Error(MessageSource.Resolver, n.tok, "type parameter '{0}' is not allowed to change the requirement
 05245          } else if (o.Characteristics.IsNonempty != n.Characteristics.IsNonempty) {
 05246            reporter.Error(MessageSource.Resolver, n.tok, "type parameter '{0}' is not allowed to change the requirement
 05247          }
 05248          if (o.Characteristics.ContainsNoReferenceTypes != n.Characteristics.ContainsNoReferenceTypes) {
 05249            reporter.Error(MessageSource.Resolver, n.tok, "type parameter '{0}' is not allowed to change the no-referenc
 05250          }
 5251
 05252        }
 05253      }
 05254      return typeMap;
 05255    }
 5256
 05257    private void CheckOverride_ResolvedParameters(IToken tok, List<Formal> old, List<Formal> nw, string name, string thi
 5258      Contract.Requires(tok != null);
 5259      Contract.Requires(old != null);
 5260      Contract.Requires(nw != null);
 5261      Contract.Requires(name != null);
 5262      Contract.Requires(thing != null);
 5263      Contract.Requires(parameterKind != null);
 5264      Contract.Requires(typeMap != null);
 05265      if (old.Count != nw.Count) {
 05266        reporter.Error(MessageSource.Resolver, tok, "{0} '{1}' is declared with a different number of {2} ({3} instead o
 05267          thing, name, parameterKind, nw.Count, old.Count);
 05268      } else {
 05269        for (int i = 0; i < old.Count; i++) {
 05270          var o = old[i];
 05271          var n = nw[i];
 05272          if (!o.IsGhost && n.IsGhost) {
 05273            reporter.Error(MessageSource.Resolver, n.tok, "{0} '{1}' of {2} {3} cannot be changed, compared to in the ov
 05274              parameterKind, n.Name, thing, name);
 05275          } else if (o.IsGhost && !n.IsGhost) {
 05276            reporter.Error(MessageSource.Resolver, n.tok, "{0} '{1}' of {2} {3} cannot be changed, compared to in the ov
 05277              parameterKind, n.Name, thing, name);
 05278          } else if (!o.IsOld && n.IsOld) {
 05279            reporter.Error(MessageSource.Resolver, n.tok, "{0} '{1}' of {2} {3} cannot be changed, compared to in the ov
 05280              parameterKind, n.Name, thing, name);
 05281          } else if (o.IsOld && !n.IsOld) {
 05282            reporter.Error(MessageSource.Resolver, n.tok, "{0} '{1}' of {2} {3} cannot be changed, compared to in the ov
 05283              parameterKind, n.Name, thing, name);
 05284          } else if (!o.IsOlder && n.IsOlder) {
 05285            reporter.Error(MessageSource.Resolver, n.tok, "{0} '{1}' of {2} {3} cannot be changed, compared to in the ov
 05286              parameterKind, n.Name, thing, name);
 05287          } else if (o.IsOlder && !n.IsOlder) {
 05288            reporter.Error(MessageSource.Resolver, n.tok, "{0} '{1}' of {2} {3} cannot be changed, compared to in the ov
 05289              parameterKind, n.Name, thing, name);
 05290          } else {
 05291            var oo = o.Type.Subst(typeMap);
 05292            if (!n.Type.Equals(oo, true)) {
 05293              reporter.Error(MessageSource.Resolver, n.tok,
 05294                "the type of {0} '{1}' is different from the type of the corresponding {0} in trait {2} ('{3}' instead o
 05295                parameterKind, n.Name, thing, n.Type, oo);
 05296            }
 05297          }
 05298        }
 05299      }
 05300    }
 5301
 5302    /// <summary>
 5303    /// Check that the SCC of 'startingPoint' can be carved up into stratospheres in such a way that each
 5304    /// datatype has some value that can be constructed from datatypes in lower stratospheres only.
 5305    /// The algorithm used here is quadratic in the number of datatypes in the SCC.  Since that number is
 5306    /// deemed to be rather small, this seems okay.
 5307    ///
 5308    /// As a side effect of this checking, the GroundingCtor field is filled in (for every inductive datatype
 5309    /// that passes the check).  It may be that several constructors could be used as the default, but
 5310    /// only the first one encountered as recorded.  This particular choice is slightly more than an
 5311    /// implementation detail, because it affects how certain cycles among inductive datatypes (having
 5312    /// to do with the types used to instantiate type parameters of datatypes) are used.
 5313    ///
 5314    /// The role of the SCC here is simply to speed up this method.  It would still be correct if the
 5315    /// equivalence classes in the given SCC were unions of actual SCC's.  In particular, this method
 5316    /// would still work if "dependencies" consisted of one large SCC containing all the inductive
 5317    /// datatypes in the module.
 5318    /// </summary>
 2695319    void SccStratosphereCheck(IndDatatypeDecl startingPoint, Graph<IndDatatypeDecl/*!*/>/*!*/ dependencies) {
 5320      Contract.Requires(startingPoint != null);
 5321      Contract.Requires(dependencies != null);  // more expensive check: Contract.Requires(cce.NonNullElements(dependenc
 5322
 2695323      var scc = dependencies.GetSCC(startingPoint);
 2695324      int totalCleared = 0;
 5385325      while (true) {
 2695326        int clearedThisRound = 0;
 16145327        foreach (var dt in scc) {
 2695328          if (dt.GroundingCtor != null) {
 5329            // previously cleared
 5385330          } else if (ComputeGroundingCtor(dt)) {
 2695331            Contract.Assert(dt.GroundingCtor != null);  // should have been set by the successful call to StratosphereCh
 2695332            clearedThisRound++;
 2695333            totalCleared++;
 2695334          }
 2695335        }
 5385336        if (totalCleared == scc.Count) {
 5337          // all is good
 2695338          return;
 05339        } else if (clearedThisRound != 0) {
 5340          // some progress was made, so let's keep going
 05341        } else {
 5342          // whatever is in scc-cleared now failed to pass the test
 05343          foreach (var dt in scc) {
 05344            if (dt.GroundingCtor == null) {
 05345              reporter.Error(MessageSource.Resolver, dt, "because of cyclic dependencies among constructor argument type
 05346            }
 05347          }
 05348          return;
 5349        }
 05350      }
 2695351    }
 5352
 5353    /// <summary>
 5354    /// Check that the datatype has some constructor all whose argument types can be constructed.
 5355    /// Returns 'true' and sets dt.GroundingCtor if that is the case.
 5356    /// </summary>
 2695357    bool ComputeGroundingCtor(IndDatatypeDecl dt) {
 5358      Contract.Requires(dt != null);
 5359      Contract.Requires(dt.GroundingCtor == null);  // the intention is that this method be called only when GroundingCt
 5360      Contract.Ensures(!Contract.Result<bool>() || dt.GroundingCtor != null);
 5361
 5362      // Stated differently, check that there is some constuctor where no argument type goes to the same stratum.
 2695363      DatatypeCtor groundingCtor = null;
 2695364      ISet<TypeParameter> lastTypeParametersUsed = null;
 25895365      foreach (DatatypeCtor ctor in dt.Ctors) {
 5945366        var typeParametersUsed = new HashSet<TypeParameter>();
 34625367        foreach (Formal p in ctor.Formals) {
 6005368          if (!CheckCanBeConstructed(p.Type, typeParametersUsed)) {
 5369            // the argument type (has a component which) is not yet known to be constructable
 305370            goto NEXT_OUTER_ITERATION;
 5371          }
 5405372        }
 5373        // this constructor satisfies the requirements, check to see if it is a better fit than the
 5374        // one found so far. Here, "better" means
 5375        //   * a ghost constructor is better than a non-ghost constructor
 5376        //   * among those, a constructor with fewer type arguments is better
 5377        //   * among those, the first one is preferred.
 8335378        if (groundingCtor == null || (!groundingCtor.IsGhost && ctor.IsGhost) || typeParametersUsed.Count < lastTypePara
 2695379          groundingCtor = ctor;
 2695380          lastTypeParametersUsed = typeParametersUsed;
 2695381        }
 5382
 17825383      NEXT_OUTER_ITERATION: { }
 5945384      }
 5385
 5385386      if (groundingCtor != null) {
 2695387        dt.GroundingCtor = groundingCtor;
 2695388        dt.TypeParametersUsedInConstructionByGroundingCtor = new bool[dt.TypeArgs.Count];
 12825389        for (int i = 0; i < dt.TypeArgs.Count; i++) {
 2485390          dt.TypeParametersUsedInConstructionByGroundingCtor[i] = lastTypeParametersUsed.Contains(dt.TypeArgs[i]);
 2485391        }
 2695392        return true;
 5393      }
 5394
 5395      // no constructor satisfied the requirements, so this is an illegal datatype declaration
 05396      return false;
 2695397    }
 5398
 6005399    bool CheckCanBeConstructed(Type type, ISet<TypeParameter> typeParametersUsed) {
 6005400      type = type.NormalizeExpandKeepConstraints();
 8105401      if (type is BasicType) {
 5402        // values of primitive types can always be constructed
 2105403        return true;
 4105404      } else if (type is CollectionType) {
 5405        // values of collection types can always be constructed
 205406        return true;
 5407      }
 5408
 3705409      var udt = (UserDefinedType)type;
 3705410      var cl = udt.ResolvedClass;
 3705411      Contract.Assert(cl != null);
 7005412      if (cl is TypeParameter) {
 5413        // treat a type parameter like a ground type
 3305414        typeParametersUsed.Add((TypeParameter)cl);
 3305415        return true;
 405416      } else if (cl is AbstractTypeDecl) {
 5417        // an opaque is like a ground type
 05418        return true;
 405419      } else if (cl is InternalTypeSynonymDecl) {
 5420        // a type exported as opaque from another module is like a ground type
 05421        return true;
 405422      } else if (cl is NewtypeDecl) {
 5423        // values of a newtype can be constructed
 05424        return true;
 405425      } else if (cl is SubsetTypeDecl) {
 05426        var td = (SubsetTypeDecl)cl;
 05427        if (td.Witness != null) {
 5428          // a witness exists, but may depend on type parameters
 05429          type.AddFreeTypeParameters(typeParametersUsed);
 05430          return true;
 05431        } else if (td.WitnessKind == SubsetTypeDecl.WKind.Special) {
 5432          // WKind.Special is only used with -->, ->, and non-null types:
 05433          Contract.Assert(ArrowType.IsPartialArrowTypeName(td.Name) || ArrowType.IsTotalArrowTypeName(td.Name) || td is 
 05434          if (ArrowType.IsTotalArrowTypeName(td.Name)) {
 05435            return CheckCanBeConstructed(udt.TypeArgs.Last(), typeParametersUsed);
 05436          } else {
 05437            return true;
 5438          }
 05439        } else {
 05440          return CheckCanBeConstructed(td.RhsWithArgument(udt.TypeArgs), typeParametersUsed);
 5441        }
 405442      } else if (cl is ClassDecl) {
 5443        // null is a value for this possibly-null type
 05444        return true;
 405445      } else if (cl is CoDatatypeDecl) {
 5446        // may depend on type parameters
 05447        type.AddFreeTypeParameters(typeParametersUsed);
 05448        return true;
 5449      }
 5450
 405451      var dependee = type.AsIndDatatype;
 405452      Contract.Assert(dependee != null);
 705453      if (dependee.GroundingCtor == null) {
 5454        // the type is an inductive datatype that we don't yet know how to construct
 305455        return false;
 5456      }
 5457      // also check the type arguments of the inductive datatype
 105458      Contract.Assert(udt.TypeArgs.Count == dependee.TypeParametersUsedInConstructionByGroundingCtor.Length);
 105459      var i = 0;
 1205460      foreach (var ta in udt.TypeArgs) {
 305461        if (dependee.TypeParametersUsedInConstructionByGroundingCtor[i] && !CheckCanBeConstructed(ta, typeParametersUsed
 05462          return false;
 5463        }
 305464        i++;
 305465      }
 105466      return true;
 6005467    }
 5468
 2695469    void DetermineEqualitySupport(IndDatatypeDecl startingPoint, Graph<IndDatatypeDecl/*!*/>/*!*/ dependencies) {
 5470      Contract.Requires(startingPoint != null);
 5471      Contract.Requires(dependencies != null);  // more expensive check: Contract.Requires(cce.NonNullElements(dependenc
 5472
 2695473      var scc = dependencies.GetSCC(startingPoint);
 5474
 05475      void MarkSCCAsNotSupportingEquality() {
 05476        foreach (var ddtt in scc) {
 05477          ddtt.EqualitySupport = IndDatatypeDecl.ES.Never;
 05478        }
 05479      }
 5480
 5481      // Look for conditions that make the whole SCC incapable of providing the equality operation:
 5482      //   * a datatype in the SCC has a ghost constructor
 5483      //   * a parameter of an inductive datatype in the SCC is ghost
 5484      //   * the type of a parameter of an inductive datatype in the SCC does not support equality
 16145485      foreach (var dt in scc) {
 2695486        Contract.Assume(dt.EqualitySupport == IndDatatypeDecl.ES.NotYetComputed);
 25895487        foreach (var ctor in dt.Ctors) {
 5945488          if (ctor.IsGhost) {
 05489            MarkSCCAsNotSupportingEquality();
 05490            return;  // we are done
 5491          }
 35525492          foreach (var arg in ctor.Formals) {
 5905493            var anotherIndDt = arg.Type.AsIndDatatype;
 5905494            if (arg.IsGhost ||
 5905495                (anotherIndDt != null && anotherIndDt.EqualitySupport == IndDatatypeDecl.ES.Never) ||
 5905496                arg.Type.IsCoDatatype ||
 5905497                arg.Type.IsArrowType) {
 5498              // arg.Type is known never to support equality
 05499              MarkSCCAsNotSupportingEquality();
 05500              return;  // we are done
 5501            }
 5905502          }
 5945503        }
 2695504      }
 5505
 5506      // Now for the more involved case:  we need to determine which type parameters determine equality support for each
 5507      // We start by seeing where each datatype's type parameters are used in a place known to determine equality suppor
 2695508      bool thingsChanged = false;
 16145509      foreach (var dt in scc) {
 3895510        if (dt.TypeArgs.Count == 0) {
 5511          // if the datatype has no type parameters, we certainly won't find any type parameters being used in the argum
 1205512          continue;
 5513        }
 14495514        foreach (var ctor in dt.Ctors) {
 20825515          foreach (var arg in ctor.Formals) {
 3605516            var typeArg = arg.Type.AsTypeParameter;
 6905517            if (typeArg != null) {
 3305518              typeArg.NecessaryForEqualitySupportOfSurroundingInductiveDatatype = true;
 3305519              thingsChanged = true;
 3605520            } else {
 305521              var otherDt = arg.Type.AsIndDatatype;
 305522              if (otherDt != null && otherDt.EqualitySupport == IndDatatypeDecl.ES.ConsultTypeArguments) {  // datatype 
 05523                var otherUdt = (UserDefinedType)arg.Type.NormalizeExpand();
 05524                var i = 0;
 05525                foreach (var otherTp in otherDt.TypeArgs) {
 05526                  if (otherTp.NecessaryForEqualitySupportOfSurroundingInductiveDatatype) {
 05527                    var tp = otherUdt.TypeArgs[i].AsTypeParameter;
 05528                    if (tp != null) {
 05529                      tp.NecessaryForEqualitySupportOfSurroundingInductiveDatatype = true;
 05530                      thingsChanged = true;
 05531                    }
 05532                  }
 05533                }
 05534              }
 305535            }
 3605536          }
 3345537        }
 1495538      }
 5539      // Then we propagate this information up through the SCC
 4495540      while (thingsChanged) {
 905541        thingsChanged = false;
 5405542        foreach (var dt in scc) {
 905543          if (dt.TypeArgs.Count == 0) {
 5544            // if the datatype has no type parameters, we certainly won't find any type parameters being used in the arg
 05545            continue;
 5546          }
 10355547          foreach (var ctor in dt.Ctors) {
 18455548            foreach (var arg in ctor.Formals) {
 3605549              var otherDt = arg.Type.AsIndDatatype;
 3605550              if (otherDt != null && otherDt.EqualitySupport == IndDatatypeDecl.ES.NotYetComputed) { // otherDt lives in
 05551                var otherUdt = (UserDefinedType)arg.Type.NormalizeExpand();
 05552                var i = 0;
 05553                foreach (var otherTp in otherDt.TypeArgs) {
 05554                  if (otherTp.NecessaryForEqualitySupportOfSurroundingInductiveDatatype) {
 05555                    var tp = otherUdt.TypeArgs[i].AsTypeParameter;
 05556                    if (tp != null && !tp.NecessaryForEqualitySupportOfSurroundingInductiveDatatype) {
 05557                      tp.NecessaryForEqualitySupportOfSurroundingInductiveDatatype = true;
 05558                      thingsChanged = true;
 05559                    }
 05560                  }
 05561                  i++;
 05562                }
 05563              }
 3605564            }
 2555565          }
 905566        }
 905567      }
 5568      // Now that we have computed the .NecessaryForEqualitySupportOfSurroundingInductiveDatatype values, mark the datat
 5569      // where equality support should be checked by looking at the type arguments.
 16145570      foreach (var dt in scc) {
 2695571        dt.EqualitySupport = IndDatatypeDecl.ES.ConsultTypeArguments;
 2695572      }
 2695573    }
 5574
 5575    /// <summary>
 5576    /// Check to see if the attribute is one that is supported by Dafny.  What check performed here is,
 5577    /// unfortunately, just an approximation, since the usage rules of a particular attribute is checked
 5578    /// elsewhere (for example, in the compiler or verifier).  It would be nice to improve this.
 5579    /// </summary>
 05580    bool IsRecognizedAttribute(UserSuppliedAttributes a, IAttributeBearingDeclaration host) {
 5581      Contract.Requires(a != null);
 5582      Contract.Requires(host != null);
 05583      switch (a.Name) {
 5584        case "opaque":
 05585          return host is Function && !(host is ExtremePredicate);
 5586        case "trigger":
 05587          return host is ComprehensionExpr || host is SetComprehension || host is MapComprehension;
 5588        case "timeLimit":
 5589        case "timeLimitMultiplier":
 05590          return host is TopLevelDecl;
 5591        case "tailrecursive":
 05592          return host is Method && !((Method)host).IsGhost;
 5593        case "autocontracts":
 05594          return host is ClassDecl;
 5595        case "autoreq":
 05596          return host is Function;
 5597        case "abstemious":
 05598          return host is Function;
 5599        case "options":
 05600          return host is ModuleDefinition;
 5601        default:
 05602          return false;
 5603      }
 05604    }
 5605
 579865606    public void ScopePushAndReport(Scope<IVariable> scope, IVariable v, string kind) {
 5607      Contract.Requires(scope != null);
 5608      Contract.Requires(v != null);
 5609      Contract.Requires(kind != null);
 579865610      ScopePushAndReport(scope, v.Name, v, v.Tok, kind);
 579865611    }
 5612
 579865613    void ScopePushAndReport<Thing>(Scope<Thing> scope, string name, Thing thing, IToken tok, string kind) where Thing : 
 5614      Contract.Requires(scope != null);
 5615      Contract.Requires(name != null);
 5616      Contract.Requires(thing != null);
 5617      Contract.Requires(tok != null);
 5618      Contract.Requires(kind != null);
 579865619      var r = scope.Push(name, thing);
 579865620      switch (r) {
 5621        case Scope<Thing>.PushResult.Success:
 579865622          break;
 5623        case Scope<Thing>.PushResult.Duplicate:
 05624          reporter.Error(MessageSource.Resolver, ErrorRegistry.NoneId, tok, "Duplicate {0} name: {1}", kind, name);
 05625          break;
 5626        case Scope<Thing>.PushResult.Shadow:
 05627          reporter.Warning(MessageSource.Resolver, ErrorRegistry.NoneId, tok, "Shadowed {0} name: {1}", kind, name);
 05628          break;
 5629      }
 579865630    }
 5631
 5632    /// <summary>
 5633    /// Assumes type parameters have already been pushed
 5634    /// </summary>
 2245635    void ResolveFunctionSignature(Function f) {
 5636      Contract.Requires(f != null);
 2245637      scope.PushMarker();
 2245638      if (f.SignatureIsOmitted) {
 05639        reporter.Error(MessageSource.Resolver, f, "function signature can be omitted only in refining functions");
 05640      }
 2245641      var option = f.TypeArgs.Count == 0 ? new ResolveTypeOption(f) : new ResolveTypeOption(ResolveTypeOptionEnum.AllowP
 13445642      foreach (Formal p in f.Formals) {
 2245643        ScopePushAndReport(scope, p, "parameter");
 2245644        ResolveType(p.tok, p.Type, f, option, f.TypeArgs);
 2245645      }
 2245646      if (f.Result != null) {
 05647        ScopePushAndReport(scope, f.Result, "parameter/return");
 05648        ResolveType(f.Result.tok, f.Result.Type, f, option, f.TypeArgs);
 2245649      } else {
 2245650        ResolveType(f.tok, f.ResultType, f, option, f.TypeArgs);
 2245651      }
 2245652      scope.PopMarker();
 2245653    }
 5654
 5655    /// <summary>
 5656    /// This method can be called even if the resolution of "fe" failed; in that case, this method will
 5657    /// not issue any error message.
 5658    /// </summary>
 05659    public void DisallowNonGhostFieldSpecifiers(FrameExpression fe) {
 5660      Contract.Requires(fe != null);
 05661      if (fe.Field != null && !fe.Field.IsGhost) {
 05662        reporter.Error(MessageSource.Resolver, fe.E, "in a ghost context, only ghost fields can be mentioned as modifies
 05663      }
 05664    }
 5665
 5666    /// <summary>
 5667    /// Assumes type parameters have already been pushed
 5668    /// </summary>
 20495669    void ResolveMethodSignature(Method m) {
 5670      Contract.Requires(m != null);
 5671
 20495672      scope.PushMarker();
 20495673      if (m.SignatureIsOmitted) {
 05674        reporter.Error(MessageSource.Resolver, m, "method signature can be omitted only in refining methods");
 05675      }
 20495676      var option = m.TypeArgs.Count == 0 ? new ResolveTypeOption(m) : new ResolveTypeOption(ResolveTypeOptionEnum.AllowP
 5677      // resolve in-parameters
 188285678      foreach (Formal p in m.Ins) {
 42275679        ScopePushAndReport(scope, p, "parameter");
 42275680        ResolveType(p.tok, p.Type, m, option, m.TypeArgs);
 42275681      }
 5682      // resolve out-parameters
 135965683      foreach (Formal p in m.Outs) {
 24835684        ScopePushAndReport(scope, p, "parameter");
 24835685        ResolveType(p.tok, p.Type, m, option, m.TypeArgs);
 24835686      }
 20495687      scope.PopMarker();
 20495688    }
 5689
 5690    /// <summary>
 5691    /// Assumes type parameters have already been pushed
 5692    /// </summary>
 05693    void ResolveIteratorSignature(IteratorDecl iter) {
 5694      Contract.Requires(iter != null);
 05695      scope.PushMarker();
 05696      if (iter.SignatureIsOmitted) {
 05697        reporter.Error(MessageSource.Resolver, iter, "iterator signature can be omitted only in refining methods");
 05698      }
 05699      var initiallyNoTypeArguments = iter.TypeArgs.Count == 0;
 05700      var option = initiallyNoTypeArguments ? new ResolveTypeOption(iter) : new ResolveTypeOption(ResolveTypeOptionEnum.
 5701      // resolve the types of the parameters
 05702      var prevErrorCount = reporter.Count(ErrorLevel.Error);
 05703      foreach (var p in iter.Ins) {
 05704        ResolveType(p.tok, p.Type, iter, option, iter.TypeArgs);
 05705      }
 05706      foreach (var p in iter.Outs) {
 05707        ResolveType(p.tok, p.Type, iter, option, iter.TypeArgs);
 05708        if (!p.Type.KnownToHaveToAValue(p.IsGhost)) {
 05709          reporter.Error(MessageSource.Resolver, p.tok, "type of yield-parameter must support auto-initialization (got '
 05710        }
 05711      }
 5712      // resolve the types of the added fields (in case some of these types would cause the addition of default type arg
 05713      if (prevErrorCount == reporter.Count(ErrorLevel.Error)) {
 05714        foreach (var p in iter.OutsHistoryFields) {
 05715          ResolveType(p.tok, p.Type, iter, option, iter.TypeArgs);
 05716        }
 05717      }
 05718      if (iter.TypeArgs.Count != iter.NonNullTypeDecl.TypeArgs.Count) {
 5719        // Apparently, the type resolution automatically added type arguments to the iterator. We'll add these to the
 5720        // corresponding non-null type as well.
 05721        Contract.Assert(initiallyNoTypeArguments);
 05722        Contract.Assert(iter.NonNullTypeDecl.TypeArgs.Count == 0);
 05723        var nnt = iter.NonNullTypeDecl;
 05724        nnt.TypeArgs.AddRange(iter.TypeArgs.ConvertAll(tp => new TypeParameter(tp.RangeToken, tp.NameNode, tp.VarianceSy
 05725        var varUdt = (UserDefinedType)nnt.Var.Type;
 05726        Contract.Assert(varUdt.TypeArgs.Count == 0);
 05727        varUdt.TypeArgs = nnt.TypeArgs.ConvertAll(tp => (Type)new UserDefinedType(tp));
 05728      }
 05729      scope.PopMarker();
 05730    }
 5731
 5732    // Like the ResolveTypeOptionEnum, but iff the case of AllowPrefixExtend, it also
 5733    // contains a pointer to its Parent class, to fill in default type parameters properly.
 5734    public class ResolveTypeOption {
 5735      public readonly ResolveTypeOptionEnum Opt;
 5736      public readonly TypeParameter.ParentType Parent;
 5737      [ContractInvariantMethod]
 05738      void ObjectInvariant() {
 5739        Contract.Invariant((Opt == ResolveTypeOptionEnum.AllowPrefixExtend) == (Parent != null));
 05740      }
 5741
 2619565742      public ResolveTypeOption(ResolveTypeOptionEnum opt) {
 5743        Contract.Requires(opt != ResolveTypeOptionEnum.AllowPrefixExtend);
 1309785744        Parent = null;
 1309785745        Opt = opt;
 1309785746      }
 5747
 41385748      public ResolveTypeOption(TypeParameter.ParentType parent) {
 5749        Contract.Requires(parent != null);
 20695750        Opt = ResolveTypeOptionEnum.AllowPrefixExtend;
 20695751        Parent = parent;
 20695752      }
 5753    }
 5754
 5755    /// <summary>
 5756    /// Returns a resolved type denoting an array type with dimension "dims" and element type "arg".
 5757    /// Callers are expected to provide "arg" as an already resolved type.  (Note, a proxy type is resolved--
 5758    /// only types that contain identifiers stand the possibility of not being resolved.)
 5759    /// </summary>
 51305760    Type ResolvedArrayType(IToken tok, int dims, Type arg, ResolutionContext resolutionContext, bool useClassNameType) {
 5761      Contract.Requires(tok != null);
 5762      Contract.Requires(1 <= dims);
 5763      Contract.Requires(arg != null);
 51305764      var at = builtIns.ArrayType(tok, dims, new List<Type> { arg }, false, useClassNameType);
 51305765      ResolveType(tok, at, resolutionContext, ResolveTypeOptionEnum.DontInfer, null);
 51305766      return at;
 51305767    }
 5768
 1755769    void FillInDefaultLoopDecreases(LoopStmt loopStmt, Expression guard, List<Expression> theDecreases, ICallable enclos
 5770      Contract.Requires(loopStmt != null);
 5771      Contract.Requires(theDecreases != null);
 5772
 1755773      if (theDecreases.Count == 0 && guard != null) {
 05774        loopStmt.InferredDecreases = true;
 05775        Expression prefix = null;
 05776        foreach (Expression guardConjunct in Expression.Conjuncts(guard)) {
 05777          Expression guess = null;
 05778          var neutralValue = Expression.CreateIntLiteral(guardConjunct.tok, -1);
 05779          if (guardConjunct is BinaryExpr bin) {
 05780            switch (bin.ResolvedOp) {
 5781              case BinaryExpr.ResolvedOpcode.Lt:
 5782              case BinaryExpr.ResolvedOpcode.Le:
 5783              case BinaryExpr.ResolvedOpcode.LtChar:
 5784              case BinaryExpr.ResolvedOpcode.LeChar:
 05785                if (bin.E0.Type.IsBigOrdinalType) {
 5786                  // we can't rely on subtracting ORDINALs, so let's just pick the upper bound and hope that works
 05787                  guess = bin.E1;
 05788                } else {
 5789                  // for A < B and A <= B, use the decreases B - A
 05790                  guess = Expression.CreateSubtract_TypeConvert(bin.E1, bin.E0);
 05791                }
 05792                break;
 5793              case BinaryExpr.ResolvedOpcode.Ge:
 5794              case BinaryExpr.ResolvedOpcode.Gt:
 5795              case BinaryExpr.ResolvedOpcode.GeChar:
 5796              case BinaryExpr.ResolvedOpcode.GtChar:
 05797                if (bin.E0.Type.IsBigOrdinalType) {
 5798                  // we can't rely on subtracting ORDINALs, so let's just pick the upper bound and hope that works
 05799                  guess = bin.E0;
 05800                } else {
 5801                  // for A >= B and A > B, use the decreases A - B
 05802                  guess = Expression.CreateSubtract_TypeConvert(bin.E0, bin.E1);
 05803                }
 05804                break;
 5805              case BinaryExpr.ResolvedOpcode.ProperSubset:
 5806              case BinaryExpr.ResolvedOpcode.Subset:
 05807                if (bin.E0.Type.AsSetType.Finite) {
 5808                  // for A < B and A <= B, use the decreases |B - A|
 05809                  guess = Expression.CreateCardinality(Expression.CreateSetDifference(bin.E1, bin.E0), builtIns);
 05810                }
 05811                break;
 5812              case BinaryExpr.ResolvedOpcode.Superset:
 5813              case BinaryExpr.ResolvedOpcode.ProperSuperset:
 05814                if (bin.E0.Type.AsSetType.Finite) {
 5815                  // for A >= B and A > B, use the decreases |A - B|
 05816                  guess = Expression.CreateCardinality(Expression.CreateSetDifference(bin.E0, bin.E1), builtIns);
 05817                }
 05818                break;
 5819              case BinaryExpr.ResolvedOpcode.ProperMultiSubset:
 5820              case BinaryExpr.ResolvedOpcode.MultiSubset:
 5821                // for A < B and A <= B, use the decreases |B - A|
 05822                guess = Expression.CreateCardinality(Expression.CreateMultisetDifference(bin.E1, bin.E0), builtIns);
 05823                break;
 5824              case BinaryExpr.ResolvedOpcode.MultiSuperset:
 5825              case BinaryExpr.ResolvedOpcode.ProperMultiSuperset:
 5826                // for A >= B and A > B, use the decreases |A - B|
 05827                guess = Expression.CreateCardinality(Expression.CreateMultisetDifference(bin.E0, bin.E1), builtIns);
 05828                break;
 5829              case BinaryExpr.ResolvedOpcode.Prefix:
 5830              case BinaryExpr.ResolvedOpcode.ProperPrefix:
 5831                // for "[] < B" and "[] <= B", use B
 05832                if (LiteralExpr.IsEmptySequence(bin.E0)) {
 05833                  guess = bin.E1;
 05834                }
 05835                break;
 5836              case BinaryExpr.ResolvedOpcode.NeqCommon:
 05837                if (bin.E0.Type.IsNumericBased() || bin.E0.Type.IsBitVectorType || bin.E0.Type.IsCharType) {
 5838                  // for A != B where A and B are numeric, use the absolute difference between A and B (that is: if A <=
 05839                  var AminusB = Expression.CreateSubtract_TypeConvert(bin.E0, bin.E1);
 05840                  var BminusA = Expression.CreateSubtract_TypeConvert(bin.E1, bin.E0);
 05841                  var test = Expression.CreateAtMost(bin.E0, bin.E1);
 05842                  guess = Expression.CreateITE(test, BminusA, AminusB);
 05843                } else if (bin.E0.Type.IsBigOrdinalType) {
 5844                  // if either of the operands is a literal, pick the other; otherwise, don't make any guess
 05845                  if (Expression.StripParens(bin.E0) is LiteralExpr) {
 05846                    guess = bin.E1;
 05847                  } else if (Expression.StripParens(bin.E1) is LiteralExpr) {
 05848                    guess = bin.E0;
 05849                  }
 05850                }
 05851                break;
 5852              case BinaryExpr.ResolvedOpcode.SetNeq:
 05853                if (bin.E0.Type.AsSetType.Finite) {
 5854                  // use |A - B| + |B - A|, but specialize it for the case where A or B is the empty set
 05855                  if (LiteralExpr.IsEmptySet(bin.E0)) {
 05856                    guess = bin.E1;
 05857                  } else if (LiteralExpr.IsEmptySet(bin.E1)) {
 05858                    guess = bin.E0;
 05859                  } else {
 05860                    var x = Expression.CreateCardinality(Expression.CreateSetDifference(bin.E0, bin.E1), builtIns);
 05861                    var y = Expression.CreateCardinality(Expression.CreateSetDifference(bin.E1, bin.E0), builtIns);
 05862                    guess = Expression.CreateAdd(x, y);
 05863                  }
 05864                }
 05865                break;
 5866              case BinaryExpr.ResolvedOpcode.MultiSetNeq:
 5867                // use |A - B| + |B - A|, but specialize it for the case where A or B is the empty multiset
 05868                if (LiteralExpr.IsEmptyMultiset(bin.E0)) {
 05869                  guess = bin.E1;
 05870                } else if (LiteralExpr.IsEmptyMultiset(bin.E1)) {
 05871                  guess = bin.E0;
 05872                } else {
 05873                  var x = Expression.CreateCardinality(Expression.CreateMultisetDifference(bin.E0, bin.E1), builtIns);
 05874                  var y = Expression.CreateCardinality(Expression.CreateMultisetDifference(bin.E1, bin.E0), builtIns);
 05875                  guess = Expression.CreateAdd(x, y);
 05876                }
 05877                break;
 5878              case BinaryExpr.ResolvedOpcode.SeqNeq:
 5879                // if either operand is [], then use the other
 05880                if (LiteralExpr.IsEmptySequence(bin.E0)) {
 05881                  guess = bin.E1;
 05882                } else if (LiteralExpr.IsEmptySequence(bin.E1)) {
 05883                  guess = bin.E0;
 05884                }
 05885                break;
 5886              default:
 05887                break;
 5888            }
 05889            if (bin.E0.Type.AsSetType != null) {
 05890              neutralValue = new SetDisplayExpr(bin.tok, bin.E0.Type.AsSetType.Finite, new List<Expression>()) {
 05891                Type = bin.E0.Type.NormalizeExpand()
 05892              };
 05893            } else if (bin.E0.Type.AsMultiSetType != null) {
 05894              neutralValue = new MultiSetDisplayExpr(bin.tok, new List<Expression>()) {
 05895                Type = bin.E0.Type.NormalizeExpand()
 05896              };
 05897            } else if (bin.E0.Type.AsSeqType != null) {
 05898              neutralValue = new SeqDisplayExpr(bin.tok, new List<Expression>()) {
 05899                Type = bin.E0.Type.NormalizeExpand()
 05900              };
 05901            } else if (bin.E0.Type.IsNumericBased(Type.NumericPersuasion.Real)) {
 05902              neutralValue = Expression.CreateRealLiteral(bin.tok, BaseTypes.BigDec.FromInt(-1));
 05903            }
 05904          }
 05905          if (guess != null) {
 05906            if (prefix != null) {
 5907              // Make the following guess:  if prefix then guess else neutralValue
 05908              guess = Expression.CreateITE(prefix, guess, neutralValue);
 05909            }
 05910            theDecreases.Add(AutoGeneratedExpression.Create(guess));
 05911          }
 05912          if (prefix == null) {
 05913            prefix = guardConjunct;
 05914          } else {
 05915            prefix = Expression.CreateAnd(prefix, guardConjunct);
 05916          }
 05917        }
 05918      }
 1755919      if (enclosingMethod is IteratorDecl) {
 05920        var iter = (IteratorDecl)enclosingMethod;
 05921        var ie = new IdentifierExpr(loopStmt.Tok, iter.YieldCountVariable.Name);
 05922        ie.Var = iter.YieldCountVariable;  // resolve here
 05923        ie.Type = iter.YieldCountVariable.Type;  // resolve here
 05924        theDecreases.Insert(0, AutoGeneratedExpression.Create(ie));
 05925        loopStmt.InferredDecreases = true;
 05926      }
 1755927      if (loopStmt.InferredDecreases && theDecreases.Count != 0) {
 05928        string s = "decreases " + Util.Comma(theDecreases, expr => Printer.ExprToString(Options, expr));
 05929        reporter.Info(MessageSource.Resolver, loopStmt.Tok, s);
 05930      }
 1755931    }
 5932
 05933    public Expression VarDotMethod(IToken tok, string varname, string methodname) {
 05934      return new ApplySuffix(tok, null, new ExprDotName(tok, new IdentifierExpr(tok, varname), methodname, null), new Li
 05935    }
 5936
 05937    public Expression makeTemp(String prefix, AssignOrReturnStmt s, ResolutionContext resolutionContext, Expression ex) 
 05938      var temp = FreshTempVarName(prefix, resolutionContext.CodeContext);
 05939      var locvar = new LocalVariable(s.RangeToken, temp, ex.Type, false);
 05940      var id = new IdentifierExpr(s.Tok, temp);
 05941      var idlist = new List<Expression>() { id };
 05942      var lhss = new List<LocalVariable>() { locvar };
 05943      var rhss = new List<AssignmentRhs>() { new ExprRhs(ex) };
 05944      var up = new UpdateStmt(s.RangeToken, idlist, rhss);
 05945      s.ResolvedStatements.Add(new VarDeclStmt(s.RangeToken, lhss, up));
 05946      return id;
 05947    }
 5948
 05949    public void EnsureSupportsErrorHandling(IToken tok, Type tp, bool expectExtract, bool hasKeywordToken) {
 5950      // The "method not found" errors which will be generated here were already reported while
 5951      // resolving the statement, so we don't want them to reappear and redirect them into a sink.
 05952      var origReporter = this.reporter;
 05953      this.reporter = new ErrorReporterSink(Options, origReporter.OuterModule);
 5954
 05955      var isFailure = ResolveMember(tok, tp, "IsFailure", out _);
 05956      var propagateFailure = ResolveMember(tok, tp, "PropagateFailure", out _);
 05957      var extract = ResolveMember(tok, tp, "Extract", out _);
 5958
 05959      if (hasKeywordToken) {
 05960        if (isFailure == null || (extract != null) != expectExtract) {
 5961          // more details regarding which methods are missing have already been reported by regular resolution
 05962          origReporter.Error(MessageSource.Resolver, tok,
 05963            "The right-hand side of ':-', which is of type '{0}', with a keyword token must have function{1}", tp,
 05964            expectExtract
 05965              ? "s 'IsFailure()' and 'Extract()'"
 05966              : " 'IsFailure()', but not 'Extract()'");
 05967        }
 05968      } else {
 05969        if (isFailure == null || propagateFailure == null || (extract != null) != expectExtract) {
 5970          // more details regarding which methods are missing have already been reported by regular resolution
 05971          origReporter.Error(MessageSource.Resolver, tok,
 05972            "The right-hand side of ':-', which is of type '{0}', must have function{1}", tp,
 05973            expectExtract
 05974              ? "s 'IsFailure()', 'PropagateFailure()', and 'Extract()'"
 05975              : "s 'IsFailure()' and 'PropagateFailure()', but not 'Extract()'");
 05976        }
 05977      }
 5978
 05979      void checkIsFunction([CanBeNull] MemberDecl memberDecl, bool allowMethod) {
 05980        if (memberDecl == null || memberDecl is Function) {
 5981          // fine
 05982        } else if (allowMethod && memberDecl is Method) {
 5983          // give a deprecation warning, so we will remove this language feature around the Dafny 4 time frame
 05984          origReporter.Deprecated(MessageSource.Resolver, ErrorRegistry.NoneId, tok,
 05985            $"Support for member '{memberDecl.Name}' in type '{tp}' (used indirectly via a :- statement) being a method 
 05986            " declare it to be a function instead");
 05987        } else {
 5988          // not allowed
 05989          origReporter.Error(MessageSource.Resolver, tok,
 05990            $"Member '{memberDecl.Name}' in type '{tp}' (used indirectly via a :- statement) is expected to be a functio
 05991        }
 05992      }
 5993
 05994      checkIsFunction(isFailure, false);
 05995      if (!hasKeywordToken) {
 05996        checkIsFunction(propagateFailure, true);
 05997      }
 05998      if (expectExtract) {
 05999        checkIsFunction(extract, true);
 06000      }
 6001
 06002      this.reporter = origReporter;
 06003    }
 6004
 6005    /// <summary>
 6006    /// Check that "stmt" is a valid statment for the body of an assert-by, forall,
 6007    /// or calc-hint statement. In particular, check that the local variables assigned in
 6008    /// the bodies of these statements are declared in the statements, not in some enclosing
 6009    /// context.
 6010    /// </summary>
 06011    public void CheckLocalityUpdates(Statement stmt, ISet<LocalVariable> localsAllowedInUpdates, string where) {
 6012      Contract.Requires(stmt != null);
 6013      Contract.Requires(localsAllowedInUpdates != null);
 6014      Contract.Requires(where != null);
 6015
 06016      if (stmt is AssertStmt || stmt is ForallStmt || stmt is CalcStmt || stmt is ModifyStmt) {
 6017        // don't recurse, since CheckHintRestrictions will be called on that assert-by separately
 06018        return;
 06019      } else if (stmt is AssignSuchThatStmt) {
 06020        var s = (AssignSuchThatStmt)stmt;
 06021        foreach (var lhs in s.Lhss) {
 06022          CheckLocalityUpdatesLhs(lhs, localsAllowedInUpdates, @where);
 06023        }
 06024      } else if (stmt is AssignStmt) {
 06025        var s = (AssignStmt)stmt;
 06026        CheckLocalityUpdatesLhs(s.Lhs, localsAllowedInUpdates, @where);
 06027      } else if (stmt is CallStmt) {
 06028        var s = (CallStmt)stmt;
 06029        foreach (var lhs in s.Lhs) {
 06030          CheckLocalityUpdatesLhs(lhs, localsAllowedInUpdates, @where);
 06031        }
 06032      } else if (stmt is VarDeclStmt) {
 06033        var s = (VarDeclStmt)stmt;
 06034        s.Locals.Iter(local => localsAllowedInUpdates.Add(local));
 06035      } else if (stmt is ModifyStmt) {
 6036        // no further complaints (note, ghost interests have already checked for 'modify' statements)
 06037      } else if (stmt is BlockStmt) {
 06038        localsAllowedInUpdates = new HashSet<LocalVariable>(localsAllowedInUpdates);
 6039        // use this new set for the recursive calls
 06040      }
 6041
 06042      foreach (var ss in stmt.SubStatements) {
 06043        CheckLocalityUpdates(ss, localsAllowedInUpdates, where);
 06044      }
 06045    }
 6046
 06047    void CheckLocalityUpdatesLhs(Expression lhs, ISet<LocalVariable> localsAllowedInUpdates, string @where) {
 6048      Contract.Requires(lhs != null);
 6049      Contract.Requires(localsAllowedInUpdates != null);
 6050      Contract.Requires(where != null);
 6051
 06052      lhs = lhs.Resolved;
 06053      if (lhs is IdentifierExpr idExpr && !localsAllowedInUpdates.Contains(idExpr.Var)) {
 06054        reporter.Error(MessageSource.Resolver, lhs.tok, "{0} is not allowed to update a variable it doesn't declare", wh
 06055      }
 06056    }
 6057
 6058    class LazyString_OnTypeEquals {
 6059      Type t0;
 6060      Type t1;
 6061      string s;
 06062      public LazyString_OnTypeEquals(Type t0, Type t1, string s) {
 6063        Contract.Requires(t0 != null);
 6064        Contract.Requires(t1 != null);
 6065        Contract.Requires(s != null);
 06066        this.t0 = t0;
 06067        this.t1 = t1;
 06068        this.s = s;
 06069      }
 06070      public override string ToString() {
 06071        return t0.Equals(t1) ? s : "";
 06072      }
 6073    }
 6074
 806075    void FindAllMembers(ClassDecl cl, string memberName, ISet<MemberDecl> foundSoFar) {
 6076      Contract.Requires(cl != null);
 6077      Contract.Requires(memberName != null);
 6078      Contract.Requires(foundSoFar != null);
 6079      MemberDecl member;
 1606080      if (classMembers[cl].TryGetValue(memberName, out member)) {
 806081        foundSoFar.Add(member);
 806082      }
 806083      cl.ParentTraitHeads.ForEach(trait => FindAllMembers(trait, memberName, foundSoFar));
 806084    }
 6085
 6086    // TODO move
 2046087    public static UserDefinedType GetThisType(IToken tok, TopLevelDeclWithMembers cl) {
 6088      Contract.Requires(tok != null);
 6089      Contract.Requires(cl != null);
 6090      Contract.Ensures(Contract.Result<UserDefinedType>() != null);
 6091
 4086092      if (cl is ClassDecl cls && cls.NonNullTypeDecl != null) {
 2046093        return UserDefinedType.FromTopLevelDecl(tok, cls.NonNullTypeDecl, cls.TypeArgs);
 06094      } else {
 06095        return UserDefinedType.FromTopLevelDecl(tok, cl, cl.TypeArgs);
 6096      }
 2046097    }
 6098
 6099    // TODO move
 06100    public static UserDefinedType GetReceiverType(IToken tok, MemberDecl member) {
 6101      Contract.Requires(tok != null);
 6102      Contract.Requires(member != null);
 6103      Contract.Ensures(Contract.Result<UserDefinedType>() != null);
 6104
 06105      return GetThisType(tok, (TopLevelDeclWithMembers)member.EnclosingClass);
 06106    }
 6107
 06108    Label/*?*/ ResolveDominatingLabelInExpr(IToken tok, string/*?*/ labelName, string expressionDescription, ResolutionC
 6109      Contract.Requires(tok != null);
 6110      Contract.Requires(expressionDescription != null);
 6111      Contract.Requires(resolutionContext != null);
 6112
 06113      Label label = null;
 06114      if (!resolutionContext.IsTwoState) {
 06115        reporter.Error(MessageSource.Resolver, tok, $"{expressionDescription} expressions are not allowed in this contex
 06116      } else if (labelName != null) {
 06117        label = DominatingStatementLabels.Find(labelName);
 06118        if (label == null) {
 06119          reporter.Error(MessageSource.Resolver, tok, $"no label '{labelName}' in scope at this time");
 06120        }
 06121      }
 06122      return label;
 06123    }
 6124
 06125    private Expression VarDotFunction(IToken tok, string varname, string functionname) {
 06126      return new ApplySuffix(tok, null, new ExprDotName(tok, new IdentifierExpr(tok, varname), functionname, null), new 
 06127    }
 6128
 6129    // TODO search for occurrences of "new LetExpr" which could benefit from this helper
 06130    private LetExpr LetPatIn(IToken tok, CasePattern<BoundVar> lhs, Expression rhs, Expression body) {
 06131      return new LetExpr(tok, new List<CasePattern<BoundVar>>() { lhs }, new List<Expression>() { rhs }, body, true);
 06132    }
 6133
 06134    private LetExpr LetVarIn(IToken tok, string name, Type tp, Expression rhs, Expression body) {
 06135      var lhs = new CasePattern<BoundVar>(tok, new BoundVar(tok, name, tp));
 06136      return LetPatIn(tok, lhs, rhs, body);
 06137    }
 6138
 6139    /// <summary>
 6140    ///  If expr.Lhs != null: Desugars "var x: T :- E; F" into "var temp := E; if temp.IsFailure() then temp.PropagateFa
 6141    ///  If expr.Lhs == null: Desugars "         :- E; F" into "var temp := E; if temp.IsFailure() then temp.PropagateFa
 6142    /// </summary>
 06143    public void ResolveLetOrFailExpr(LetOrFailExpr expr, ResolutionContext resolutionContext) {
 06144      var temp = FreshTempVarName("valueOrError", resolutionContext.CodeContext);
 06145      var tempType = new InferredTypeProxy();
 6146      // "var temp := E;"
 06147      expr.ResolvedExpression = LetVarIn(expr.tok, temp, tempType, expr.Rhs,
 06148        // "if temp.IsFailure()"
 06149        new ITEExpr(expr.tok, false, VarDotFunction(expr.tok, temp, "IsFailure"),
 06150          // "then temp.PropagateFailure()"
 06151          VarDotFunction(expr.tok, temp, "PropagateFailure"),
 06152          // "else"
 06153          expr.Lhs == null
 06154            // "F"
 06155            ? expr.Body
 06156            // "var x: T := temp.Extract(); F"
 06157            : LetPatIn(expr.tok, expr.Lhs, VarDotFunction(expr.tok, temp, "Extract"), expr.Body)));
 6158
 06159      ResolveExpression(expr.ResolvedExpression, resolutionContext);
 06160      expr.Type = expr.ResolvedExpression.Type;
 06161      bool expectExtract = (expr.Lhs != null);
 06162      EnsureSupportsErrorHandling(expr.tok, PartiallyResolveTypeForMemberSelection(expr.tok, tempType), expectExtract, f
 06163    }
 6164
 06165    public static Type SelectAppropriateArrowTypeForFunction(Function function, Dictionary<TypeParameter, Type> subst, B
 06166      return SelectAppropriateArrowType(function.tok,
 06167        function.Formals.ConvertAll(formal => formal.Type.Subst(subst)),
 06168        function.ResultType.Subst(subst),
 06169        function.Reads.Count != 0, function.Req.Count != 0,
 06170        builtIns);
 06171    }
 6172
 06173    public static Type SelectAppropriateArrowType(IToken tok, List<Type> typeArgs, Type resultType, bool hasReads, bool 
 6174      Contract.Requires(tok != null);
 6175      Contract.Requires(typeArgs != null);
 6176      Contract.Requires(resultType != null);
 06177      var arity = typeArgs.Count;
 06178      var typeArgsAndResult = Util.Snoc(typeArgs, resultType);
 06179      if (hasReads) {
 6180        // any arrow
 06181        return new ArrowType(tok, builtIns.ArrowTypeDecls[arity], typeArgsAndResult);
 06182      } else if (hasReq) {
 6183        // partial arrow
 06184        return new UserDefinedType(tok, ArrowType.PartialArrowTypeName(arity), builtIns.PartialArrowTypeDecls[arity], ty
 06185      } else {
 6186        // total arrow
 06187        return new UserDefinedType(tok, ArrowType.TotalArrowTypeName(arity), builtIns.TotalArrowTypeDecls[arity], typeAr
 6188      }
 06189    }
 6190
 6191    /// <summary>
 6192    /// Adds appropriate type constraints that says "expr" evaluates to an integer or (if "allowBitVector" is true) a
 6193    /// a bitvector.  The "errFormat" string can contain a "{0}", referring to the name of the type of "expr".
 6194    /// </summary>
 43056195    void ConstrainToIntegerType(Expression expr, bool allowBitVector, string errFormat) {
 6196      Contract.Requires(expr != null);
 6197      Contract.Requires(errFormat != null);
 43056198      var err = new TypeConstraint.ErrorMsgWithToken(expr.tok, errFormat, expr.Type);
 43056199      ConstrainToIntegerType(expr.tok, expr.Type, allowBitVector, err);
 43056200    }
 6201
 6202    /// <summary>
 6203    /// Resolves a NestedMatchExpr by
 6204    /// 1 - checking that all of its patterns are linear
 6205    /// 2 - desugaring it into a decision tree of MatchExpr and ITEEXpr (for constant matching)
 6206    /// 3 - resolving the generated (sub)expression.
 6207    /// </summary>
 32646208    void ResolveNestedMatchExpr(NestedMatchExpr nestedMatchExpr, ResolutionContext resolutionContext) {
 6209      Contract.Requires(nestedMatchExpr != null);
 6210      Contract.Requires(resolutionContext != null);
 6211
 32646212      nestedMatchExpr.Resolve(this, resolutionContext);
 32646213    }
 6214
 6215    void ResolveCasePattern<VT>(CasePattern<VT> pat, Type sourceType, ResolutionContext resolutionContext)
 06216      where VT : class, IVariable {
 6217      Contract.Requires(pat != null);
 6218      Contract.Requires(sourceType != null);
 6219      Contract.Requires(resolutionContext != null);
 6220
 06221      DatatypeDecl dtd = null;
 06222      UserDefinedType udt = null;
 06223      if (sourceType.IsDatatype) {
 06224        udt = (UserDefinedType)sourceType.NormalizeExpand();
 06225        dtd = (DatatypeDecl)udt.ResolvedClass;
 06226      }
 6227      // Find the constructor in the given datatype
 6228      // If what was parsed was just an identifier, we will interpret it as a datatype constructor, if possible
 06229      DatatypeCtor ctor = null;
 06230      if (dtd != null) {
 06231        if (pat.Var == null || (pat.Var != null && pat.Var.Type is TypeProxy)) {
 06232          if (dtd.ConstructorsByName.TryGetValue(pat.Id, out ctor)) {
 06233            if (pat.Arguments == null) {
 06234              if (ctor.Formals.Count != 0) {
 6235                // Leave this as a variable
 06236              } else {
 6237                // Convert to a constructor
 06238                pat.MakeAConstructor();
 06239                pat.Ctor = ctor;
 06240                pat.Var = default(VT);
 06241              }
 06242            } else {
 06243              pat.Ctor = ctor;
 06244              pat.Var = default(VT);
 06245            }
 06246          }
 06247        }
 06248      }
 6249
 06250      if (pat.Var != null) {
 6251        // this is a simple resolution
 06252        var v = pat.Var;
 06253        if (resolutionContext.IsGhost) {
 06254          v.MakeGhost();
 06255        }
 06256        ResolveType(v.Tok, v.Type, resolutionContext, ResolveTypeOptionEnum.InferTypeProxies, null);
 6257        // Note, the following type constraint checks that the RHS type can be assigned to the new variable on the left.
 6258        // does not check that the entire RHS can be assigned to something of the type of the pattern on the left.  For 
 6259        // a type declared as "datatype Atom<T> = MakeAtom(T)", where T is a non-variant type argument.  Suppose the RHS
 6260        // and that the LHS is the pattern MakeAtom(x: int).  This is okay, despite the fact that Atom<nat> is not assig
 6261        // The reason is that the purpose of the pattern on the left is really just to provide a skeleton to introduce b
 06262        EagerAddAssignableConstraint(v.Tok, v.Type, sourceType, "type of corresponding source/RHS ({1}) does not match t
 06263        pat.AssembleExpr(null);
 06264        return;
 6265      }
 06266      if (dtd == null) {
 6267        // look up the name of the pattern's constructor
 6268        Tuple<DatatypeCtor, bool> pair;
 06269        if (moduleInfo.Ctors.TryGetValue(pat.Id, out pair) && !pair.Item2) {
 06270          ctor = pair.Item1;
 06271          pat.Ctor = ctor;
 06272          dtd = ctor.EnclosingDatatype;
 06273          var typeArgs = new List<Type>();
 06274          foreach (var xt in dtd.TypeArgs) {
 06275            typeArgs.Add(new InferredTypeProxy());
 06276          }
 06277          udt = new UserDefinedType(pat.tok, dtd.Name, dtd, typeArgs);
 06278          ConstrainSubtypeRelation(udt, sourceType, pat.tok, "type of RHS ({0}) does not match type of bound variable '{
 06279        }
 06280      }
 06281      if (dtd == null && ctor == null) {
 06282        reporter.Error(MessageSource.Resolver, pat.tok, "to use a pattern, the type of the source/RHS expression must be
 06283      } else if (ctor == null) {
 06284        reporter.Error(MessageSource.Resolver, pat.tok, "constructor {0} does not exist in datatype {1}", pat.Id, dtd.Na
 06285      } else {
 06286        if (pat.Arguments == null) {
 06287          if (ctor.Formals.Count == 0) {
 6288            // The Id matches a constructor of the correct type and 0 arguments,
 6289            // so make it a nullary constructor, not a variable
 06290            pat.MakeAConstructor();
 06291          }
 06292        } else {
 06293          if (ctor.Formals.Count != pat.Arguments.Count) {
 06294            reporter.Error(MessageSource.Resolver, pat.tok, "pattern for constructor {0} has wrong number of formals (fo
 06295          }
 06296        }
 6297        // build the type-parameter substitution map for this use of the datatype
 06298        Contract.Assert(dtd.TypeArgs.Count == udt.TypeArgs.Count);  // follows from the type previously having been succ
 06299        var subst = TypeParameter.SubstitutionMap(dtd.TypeArgs, udt.TypeArgs);
 6300        // recursively call ResolveCasePattern on each of the arguments
 06301        var j = 0;
 06302        if (pat.Arguments != null) {
 06303          foreach (var arg in pat.Arguments) {
 06304            if (j < ctor.Formals.Count) {
 06305              var formal = ctor.Formals[j];
 06306              Type st = formal.Type.Subst(subst);
 06307              ResolveCasePattern(arg, st, resolutionContext.WithGhost(resolutionContext.IsGhost || formal.IsGhost));
 06308            }
 06309            j++;
 06310          }
 06311        }
 06312        if (j == ctor.Formals.Count) {
 06313          pat.AssembleExpr(udt.TypeArgs);
 06314        }
 06315      }
 06316    }
 6317
 1126318    private List<DefaultValueExpression> allDefaultValueExpressions = new List<DefaultValueExpression>();
 6319
 6320    /// <summary>
 6321    /// This method is called at the tail end of Pass1 of the Resolver.
 6322    /// </summary>
 3266323    void FillInDefaultValueExpressions() {
 3266324      var visited = new Dictionary<DefaultValueExpression, WorkProgress>();
 9786325      foreach (var e in allDefaultValueExpressions) {
 06326        FillInDefaultValueExpression(e, visited);
 06327      }
 3266328      allDefaultValueExpressions.Clear();
 3266329    }
 6330
 6331    enum WorkProgress { BeingVisited, Done }
 6332
 06333    void FillInDefaultValueExpression(DefaultValueExpression expr, Dictionary<DefaultValueExpression, WorkProgress> visi
 6334      Contract.Requires(expr != null);
 6335      Contract.Requires(visited != null);
 6336      Contract.Ensures(expr.ResolvedExpression != null);
 6337
 06338      if (visited.TryGetValue(expr, out var p)) {
 06339        if (p == WorkProgress.Done) {
 06340          Contract.Assert(expr.ResolvedExpression != null);
 06341        } else {
 6342          // there is a cycle
 06343          reporter.Error(MessageSource.Resolver, expr, "default-valued expressions are cyclicly dependent; this is not a
 6344          // nevertheless, to avoid any issues in the resolver, fill in the .ResolvedExpression field with something
 06345          expr.ResolvedExpression = Expression.CreateBoolLiteral(expr.tok, false);
 06346        }
 06347        return;
 6348      }
 06349      Contract.Assert(expr.ResolvedExpression == null);
 6350
 06351      visited.Add(expr, WorkProgress.BeingVisited);
 06352      var s = new DefaultValueSubstituter(this, visited, expr.Receiver, expr.SubstMap, expr.TypeMap);
 06353      expr.ResolvedExpression = s.Substitute(expr.Formal.DefaultValue);
 06354      visited[expr] = WorkProgress.Done;
 06355    }
 6356
 6357    class DefaultValueSubstituter : Substituter {
 6358      private readonly Resolver resolver;
 6359      private readonly Dictionary<DefaultValueExpression, WorkProgress> visited;
 6360      public DefaultValueSubstituter(Resolver resolver, Dictionary<DefaultValueExpression, WorkProgress> visited,
 6361        Expression /*?*/ receiverReplacement, Dictionary<IVariable, Expression> substMap, Dictionary<TypeParameter, Type
 06362        : base(receiverReplacement, substMap, typeMap) {
 6363        Contract.Requires(resolver != null);
 6364        Contract.Requires(visited != null);
 06365        this.resolver = resolver;
 06366        this.visited = visited;
 06367      }
 6368
 06369      public override Expression Substitute(Expression expr) {
 06370        if (expr is DefaultValueExpression dve) {
 06371          resolver.FillInDefaultValueExpression(dve, visited);
 06372          Contract.Assert(dve.ResolvedExpression != null); // postcondition of FillInDefaultValueExpression
 06373        }
 06374        return base.Substitute(expr);
 06375      }
 6376    }
 6377
 6378    public Dictionary<TypeParameter, Type> BuildTypeArgumentSubstitute(Dictionary<TypeParameter, Type> typeArgumentSubst
 112956379      Type/*?*/ receiverTypeBound = null) {
 6380      Contract.Requires(typeArgumentSubstitutions != null);
 6381
 112956382      var subst = new Dictionary<TypeParameter, Type>();
 917406383      foreach (var entry in typeArgumentSubstitutions) {
 192856384        subst.Add(entry.Key, entry.Value);
 192856385      }
 6386
 112956387      if (SelfTypeSubstitution != null) {
 06388        foreach (var entry in SelfTypeSubstitution) {
 06389          subst.Add(entry.Key, entry.Value);
 06390        }
 06391      }
 6392
 225906393      if (receiverTypeBound != null) {
 112956394        subst = AddParentTypeParameterSubstitutions(subst, receiverTypeBound);
 112956395      }
 6396
 112956397      return subst;
 112956398    }
 6399
 112956400    public static Dictionary<TypeParameter, Type> AddParentTypeParameterSubstitutions(Dictionary<TypeParameter, Type> su
 6401      TopLevelDeclWithMembers cl;
 112956402      var udt = receiverType?.AsNonNullRefType;
 112956403      if (udt != null) {
 06404        cl = (TopLevelDeclWithMembers)((NonNullTypeDecl)udt.ResolvedClass).ViewAsClass;
 112956405      } else {
 112956406        udt = receiverType.NormalizeExpand() as UserDefinedType;
 112956407        cl = udt?.ResolvedClass as TopLevelDeclWithMembers;
 112956408      }
 224256409      if (cl != null) {
 333906410        foreach (var entry in cl.ParentFormalTypeParametersToActuals) {
 06411          var v = entry.Value.Subst(subst);
 06412          subst.Add(entry.Key, v);
 06413        }
 111306414      }
 6415
 112956416      return subst;
 112956417    }
 6418
 31526419    public static string GhostPrefix(bool isGhost) {
 31526420      return isGhost ? "ghost " : "";
 31526421    }
 6422
 06423    private static ModuleSignature GetSignatureExt(ModuleSignature sig, bool useCompileSignatures) {
 6424      Contract.Requires(sig != null);
 6425      Contract.Ensures(Contract.Result<ModuleSignature>() != null);
 06426      if (useCompileSignatures) {
 06427        while (sig.CompileSignature != null) {
 06428          sig = sig.CompileSignature;
 06429        }
 06430      }
 06431      return sig;
 06432    }
 6433
 06434    private ModuleSignature GetSignature(ModuleSignature sig) {
 06435      return GetSignatureExt(sig, useCompileSignatures);
 06436    }
 6437
 1026438    public static Expression GetImpliedTypeConstraint(IVariable bv, Type ty) {
 1026439      return GetImpliedTypeConstraint(Expression.CreateIdentExpr(bv), ty);
 1026440    }
 6441
 2046442    public static Expression GetImpliedTypeConstraint(Expression e, Type ty) {
 6443      Contract.Requires(e != null);
 6444      Contract.Requires(ty != null);
 2046445      ty = ty.NormalizeExpandKeepConstraints();
 2046446      var udt = ty as UserDefinedType;
 3066447      if (udt != null) {
 1026448        if (udt.ResolvedClass is NewtypeDecl) {
 06449          var dd = (NewtypeDecl)udt.ResolvedClass;
 06450          var c = GetImpliedTypeConstraint(e, dd.BaseType);
 06451          if (dd.Var != null) {
 06452            Dictionary<IVariable, Expression/*!*/> substMap = new Dictionary<IVariable, Expression>();
 06453            substMap.Add(dd.Var, e);
 06454            Substituter sub = new Substituter(null, substMap, new Dictionary<TypeParameter, Type>());
 06455            c = Expression.CreateAnd(c, sub.Substitute(dd.Constraint));
 06456          }
 06457          return c;
 2046458        } else if (udt.ResolvedClass is SubsetTypeDecl) {
 1026459          var dd = (SubsetTypeDecl)udt.ResolvedClass;
 1026460          var c = GetImpliedTypeConstraint(e, dd.RhsWithArgument(udt.TypeArgs));
 1026461          Dictionary<IVariable, Expression/*!*/> substMap = new Dictionary<IVariable, Expression>();
 1026462          substMap.Add(dd.Var, e);
 1026463          Substituter sub = new Substituter(null, substMap, new Dictionary<TypeParameter, Type>());
 1026464          c = Expression.CreateAnd(c, sub.Substitute(dd.Constraint));
 1026465          return c;
 6466        }
 06467      }
 1026468      return Expression.CreateBoolLiteral(e.tok, true);
 2046469    }
 6470
 6471    /// <summary>
 6472    /// Returns the set of free variables in "expr".
 6473    /// Requires "expr" to be successfully resolved.
 6474    /// Ensures that the set returned has no aliases.
 6475    /// </summary>
 06476    static ISet<IVariable> FreeVariables(Expression expr) {
 6477      Contract.Requires(expr != null);
 6478      Contract.Ensures(expr.Type != null);
 6479
 06480      if (expr is IdentifierExpr) {
 06481        var e = (IdentifierExpr)expr;
 06482        return new HashSet<IVariable>() { e.Var };
 6483
 06484      } else if (expr is QuantifierExpr) {
 06485        var e = (QuantifierExpr)expr;
 06486        Contract.Assert(e.SplitQuantifier == null); // No split quantifiers during resolution
 6487
 06488        var s = FreeVariables(e.LogicalBody());
 06489        foreach (var bv in e.BoundVars) {
 06490          s.Remove(bv);
 06491        }
 06492        return s;
 06493      } else if (expr is NestedMatchExpr) {
 06494        var e = (NestedMatchExpr)expr;
 06495        var s = FreeVariables(e.Source);
 06496        foreach (NestedMatchCaseExpr mc in e.Cases) {
 06497          var t = FreeVariables(mc.Body);
 06498          foreach (var bv in mc.Pat.Children.OfType<IdPattern>()) {
 06499            if (bv.BoundVar != null) {
 06500              t.Remove(bv.BoundVar);
 06501            }
 06502          }
 06503          s.UnionWith(t);
 06504        }
 06505        return s;
 06506      } else if (expr is MatchExpr) {
 06507        var e = (MatchExpr)expr;
 06508        var s = FreeVariables(e.Source);
 06509        foreach (MatchCaseExpr mc in e.Cases) {
 06510          var t = FreeVariables(mc.Body);
 06511          foreach (var bv in mc.Arguments) {
 06512            t.Remove(bv);
 06513          }
 06514          s.UnionWith(t);
 06515        }
 06516        return s;
 6517
 06518      } else if (expr is LambdaExpr) {
 06519        var e = (LambdaExpr)expr;
 06520        var s = FreeVariables(e.Term);
 06521        if (e.Range != null) {
 06522          s.UnionWith(FreeVariables(e.Range));
 06523        }
 06524        foreach (var fe in e.Reads) {
 06525          s.UnionWith(FreeVariables(fe.E));
 06526        }
 06527        foreach (var bv in e.BoundVars) {
 06528          s.Remove(bv);
 06529        }
 06530        return s;
 6531
 06532      } else {
 06533        ISet<IVariable> s = null;
 06534        foreach (var e in expr.SubExpressions) {
 06535          var t = FreeVariables(e);
 06536          if (s == null) {
 06537            s = t;
 06538          } else {
 06539            s.UnionWith(t);
 06540          }
 06541        }
 06542        return s == null ? new HashSet<IVariable>() : s;
 6543      }
 06544    }
 6545
 6546    /// <summary>
 6547    /// An error message for the type constraint for between a sequence select expression's actual and expected types.
 6548    /// If resolution successfully determines the sequences' element types, then this derived class mentions those
 6549    /// element types as clarifying context to the user.
 6550    /// </summary>
 6551    private class SeqSelectOneErrorMsg : TypeConstraint.ErrorMsgWithToken {
 676552      private static readonly string BASE_MESSAGE_FORMAT = "sequence has type {0} which is incompatible with expected ty
 676553      private static readonly string ELEMENT_DETAIL_MESSAGE_FORMAT = " (element type {0} is incompatible with {1})";
 6554
 6555      private readonly Type exprSeqType;
 6556      private readonly Type expectedSeqType;
 6557
 6558      public override string Msg {
 06559        get {
 6560          // Resolution might resolve exprSeqType/expectedSeqType to not be sequences at all.
 6561          // In that case, it isn't possible to get the corresponding element types.
 06562          var rawExprElementType = exprSeqType.AsSeqType?.Arg;
 06563          var rawExpectedElementType = expectedSeqType.AsSeqType?.Arg;
 06564          if (rawExprElementType == null || rawExpectedElementType == null) {
 06565            return base.Msg;
 6566          }
 6567
 06568          var elementTypes = RemoveAmbiguity(new object[] { rawExprElementType, rawExpectedElementType });
 06569          Contract.Assert(elementTypes.Length == 2);
 06570          var exprElementType = elementTypes[0].ToString();
 06571          var expectedElementType = elementTypes[1].ToString();
 6572
 06573          string detail = string.Format(ELEMENT_DETAIL_MESSAGE_FORMAT, exprElementType, expectedElementType);
 06574          return base.Msg + detail;
 06575        }
 6576      }
 6577
 6578      public SeqSelectOneErrorMsg(IToken tok, Type exprSeqType, Type expectedSeqType)
 255326579        : base(tok, BASE_MESSAGE_FORMAT, exprSeqType, expectedSeqType) {
 6580        Contract.Requires(exprSeqType != null);
 6581        Contract.Requires(expectedSeqType != null);
 127666582        this.exprSeqType = exprSeqType;
 127666583        this.expectedSeqType = expectedSeqType;
 127666584      }
 6585    }
 6586
 6587    /// <summary>
 6588    /// Note: this method is allowed to be called even if "type" does not make sense for "op", as might be the case if
 6589    /// resolution of the binary expression failed.  If so, an arbitrary resolved opcode is returned.
 6590    /// Usually, the type of the right-hand operand is used to determine the resolved operator (hence, the shorter
 6591    /// name "operandType" instead of, say, "rightOperandType").
 6592    /// </summary>
 644886593    public static BinaryExpr.ResolvedOpcode ResolveOp(BinaryExpr.Opcode op, Type leftOperandType, Type operandType) {
 6594      Contract.Requires(leftOperandType != null);
 6595      Contract.Requires(operandType != null);
 644886596      leftOperandType = leftOperandType.NormalizeExpand();
 644886597      operandType = operandType.NormalizeExpand();
 644886598      switch (op) {
 656599        case BinaryExpr.Opcode.Iff: return BinaryExpr.ResolvedOpcode.Iff;
 45426600        case BinaryExpr.Opcode.Imp: return BinaryExpr.ResolvedOpcode.Imp;
 806601        case BinaryExpr.Opcode.Exp: return BinaryExpr.ResolvedOpcode.Imp;
 111666602        case BinaryExpr.Opcode.And: return BinaryExpr.ResolvedOpcode.And;
 15886603        case BinaryExpr.Opcode.Or: return BinaryExpr.ResolvedOpcode.Or;
 6604        case BinaryExpr.Opcode.Eq:
 219716605          if (operandType is SetType) {
 3106606            return BinaryExpr.ResolvedOpcode.SetEq;
 215716607          } else if (operandType is MultiSetType) {
 2206608            return BinaryExpr.ResolvedOpcode.MultiSetEq;
 222756609          } else if (operandType is SeqType) {
 11446610            return BinaryExpr.ResolvedOpcode.SeqEq;
 217896611          } else if (operandType is MapType) {
 18026612            return BinaryExpr.ResolvedOpcode.MapEq;
 181856613          } else {
 181856614            return BinaryExpr.ResolvedOpcode.EqCommon;
 6615          }
 6616        case BinaryExpr.Opcode.Neq:
 11306617          if (operandType is SetType) {
 106618            return BinaryExpr.ResolvedOpcode.SetNeq;
 11106619          } else if (operandType is MultiSetType) {
 06620            return BinaryExpr.ResolvedOpcode.MultiSetNeq;
 11106621          } else if (operandType is SeqType) {
 06622            return BinaryExpr.ResolvedOpcode.SeqNeq;
 11106623          } else if (operandType is MapType) {
 06624            return BinaryExpr.ResolvedOpcode.MapNeq;
 11106625          } else {
 11106626            return BinaryExpr.ResolvedOpcode.NeqCommon;
 6627          }
 6628        case BinaryExpr.Opcode.Disjoint:
 606629          if (operandType is MultiSetType) {
 206630            return BinaryExpr.ResolvedOpcode.MultiSetDisjoint;
 206631          } else {
 206632            return BinaryExpr.ResolvedOpcode.Disjoint;
 6633          }
 6634        case BinaryExpr.Opcode.Lt:
 41246635          if (operandType.IsIndDatatype) {
 06636            return BinaryExpr.ResolvedOpcode.RankLt;
 41446637          } else if (operandType is SetType) {
 206638            return BinaryExpr.ResolvedOpcode.ProperSubset;
 41046639          } else if (operandType is MultiSetType) {
 06640            return BinaryExpr.ResolvedOpcode.ProperMultiSubset;
 41246641          } else if (operandType is SeqType) {
 206642            return BinaryExpr.ResolvedOpcode.ProperPrefix;
 40846643          } else if (operandType is CharType) {
 06644            return BinaryExpr.ResolvedOpcode.LtChar;
 40846645          } else {
 40846646            return BinaryExpr.ResolvedOpcode.Lt;
 6647          }
 6648        case BinaryExpr.Opcode.Le:
 30136649          if (operandType is SetType) {
 06650            return BinaryExpr.ResolvedOpcode.Subset;
 30236651          } else if (operandType is MultiSetType) {
 106652            return BinaryExpr.ResolvedOpcode.MultiSubset;
 30036653          } else if (operandType is SeqType) {
 06654            return BinaryExpr.ResolvedOpcode.Prefix;
 30236655          } else if (operandType is CharType) {
 206656            return BinaryExpr.ResolvedOpcode.LeChar;
 29836657          } else {
 29836658            return BinaryExpr.ResolvedOpcode.Le;
 6659          }
 6660        case BinaryExpr.Opcode.LeftShift:
 06661          return BinaryExpr.ResolvedOpcode.LeftShift;
 6662        case BinaryExpr.Opcode.RightShift:
 06663          return BinaryExpr.ResolvedOpcode.RightShift;
 6664        case BinaryExpr.Opcode.Add:
 13656665          if (operandType is SetType) {
 356666            return BinaryExpr.ResolvedOpcode.Union;
 13406667          } else if (operandType is MultiSetType) {
 456668            return BinaryExpr.ResolvedOpcode.MultiSetUnion;
 14906669          } else if (operandType is MapType) {
 2406670            return BinaryExpr.ResolvedOpcode.MapMerge;
 13756671          } else if (operandType is SeqType) {
 3656672            return BinaryExpr.ResolvedOpcode.Concat;
 6456673          } else {
 6456674            return BinaryExpr.ResolvedOpcode.Add;
 6675          }
 6676        case BinaryExpr.Opcode.Sub:
 15836677          if (leftOperandType is MapType) {
 2846678            return BinaryExpr.ResolvedOpcode.MapSubtraction;
 10606679          } else if (operandType is SetType) {
 456680            return BinaryExpr.ResolvedOpcode.SetDifference;
 10106681          } else if (operandType is MultiSetType) {
 406682            return BinaryExpr.ResolvedOpcode.MultiSetDifference;
 9306683          } else {
 9306684            return BinaryExpr.ResolvedOpcode.Sub;
 6685          }
 6686        case BinaryExpr.Opcode.Mul:
 2056687          if (operandType is SetType) {
 106688            return BinaryExpr.ResolvedOpcode.Intersection;
 2006689          } else if (operandType is MultiSetType) {
 156690            return BinaryExpr.ResolvedOpcode.MultiSetIntersection;
 1706691          } else {
 1706692            return BinaryExpr.ResolvedOpcode.Mul;
 6693          }
 6694        case BinaryExpr.Opcode.Gt:
 70436695          if (operandType.IsDatatype) {
 06696            return BinaryExpr.ResolvedOpcode.RankGt;
 70686697          } else if (operandType is SetType) {
 256698            return BinaryExpr.ResolvedOpcode.ProperSuperset;
 70486699          } else if (operandType is MultiSetType) {
 306700            return BinaryExpr.ResolvedOpcode.ProperMultiSuperset;
 69986701          } else if (operandType is CharType) {
 106702            return BinaryExpr.ResolvedOpcode.GtChar;
 69786703          } else {
 69786704            return BinaryExpr.ResolvedOpcode.Gt;
 6705          }
 6706        case BinaryExpr.Opcode.Ge:
 16846707          if (operandType is SetType) {
 106708            return BinaryExpr.ResolvedOpcode.Superset;
 16796709          } else if (operandType is MultiSetType) {
 156710            return BinaryExpr.ResolvedOpcode.MultiSuperset;
 16596711          } else if (operandType is CharType) {
 106712            return BinaryExpr.ResolvedOpcode.GeChar;
 16396713          } else {
 16396714            return BinaryExpr.ResolvedOpcode.Ge;
 6715          }
 6716        case BinaryExpr.Opcode.In:
 41576717          if (operandType is SetType) {
 206718            return BinaryExpr.ResolvedOpcode.InSet;
 41276719          } else if (operandType is MultiSetType) {
 106720            return BinaryExpr.ResolvedOpcode.InMultiSet;
 81946721          } else if (operandType is MapType) {
 40876722            return BinaryExpr.ResolvedOpcode.InMap;
 206723          } else {
 206724            return BinaryExpr.ResolvedOpcode.InSeq;
 6725          }
 6726        case BinaryExpr.Opcode.NotIn:
 1606727          if (operandType is SetType) {
 306728            return BinaryExpr.ResolvedOpcode.NotInSet;
 1306729          } else if (operandType is MultiSetType) {
 306730            return BinaryExpr.ResolvedOpcode.NotInMultiSet;
 1306731          } else if (operandType is MapType) {
 606732            return BinaryExpr.ResolvedOpcode.NotInMap;
 106733          } else {
 106734            return BinaryExpr.ResolvedOpcode.NotInSeq;
 6735          }
 6686736        case BinaryExpr.Opcode.Div: return BinaryExpr.ResolvedOpcode.Div;
 6136737        case BinaryExpr.Opcode.Mod: return BinaryExpr.ResolvedOpcode.Mod;
 06738        case BinaryExpr.Opcode.BitwiseAnd: return BinaryExpr.ResolvedOpcode.BitwiseAnd;
 06739        case BinaryExpr.Opcode.BitwiseOr: return BinaryExpr.ResolvedOpcode.BitwiseOr;
 06740        case BinaryExpr.Opcode.BitwiseXor: return BinaryExpr.ResolvedOpcode.BitwiseXor;
 6741        default:
 06742          Contract.Assert(false); throw new cce.UnreachableException();  // unexpected operator
 6743      }
 644886744    }
 6745
 6746    /// <summary>
 6747    /// This method adds to "friendlyCalls" all
 6748    ///     inductive calls                                     if !co
 6749    ///     greatest predicate calls and codatatype equalities  if co
 6750    /// that occur in positive positions and not under
 6751    ///     universal quantification                            if !co
 6752    ///     existential quantification.                         if co
 6753    /// If "expr" is the
 6754    ///     precondition of a least lemma                       if !co
 6755    ///     postcondition of a greatest lemma,                  if co
 6756    /// then the "friendlyCalls" are the subexpressions that need to be replaced in order
 6757    /// to create the
 6758    ///     precondition                                        if !co
 6759    ///     postcondition                                       if co
 6760    /// of the corresponding prefix lemma.
 6761    /// </summary>
 06762    void CollectFriendlyCallsInExtremeLemmaSpecification(Expression expr, bool position, ISet<Expression> friendlyCalls,
 6763      Contract.Requires(expr != null);
 6764      Contract.Requires(friendlyCalls != null);
 06765      var visitor = new CollectFriendlyCallsInSpec_Visitor(this, friendlyCalls, co, context);
 06766      visitor.Visit(expr, position ? CallingPosition.Positive : CallingPosition.Negative);
 06767    }
 6768
 6769    class CollectFriendlyCallsInSpec_Visitor : FindFriendlyCalls_Visitor {
 6770      readonly ISet<Expression> friendlyCalls;
 6771      readonly ExtremeLemma Context;
 6772      public CollectFriendlyCallsInSpec_Visitor(Resolver resolver, ISet<Expression> friendlyCalls, bool co, ExtremeLemma
 06773        : base(resolver, co, context.KNat) {
 6774        Contract.Requires(resolver != null);
 6775        Contract.Requires(friendlyCalls != null);
 6776        Contract.Requires(context != null);
 06777        this.friendlyCalls = friendlyCalls;
 06778        this.Context = context;
 06779      }
 06780      protected override bool VisitOneExpr(Expression expr, ref CallingPosition cp) {
 06781        if (cp == CallingPosition.Neither) {
 6782          // no friendly calls in "expr"
 06783          return false;  // don't recurse into subexpressions
 6784        }
 06785        if (expr is FunctionCallExpr) {
 06786          if (cp == CallingPosition.Positive) {
 06787            var fexp = (FunctionCallExpr)expr;
 06788            if (IsCoContext ? fexp.Function is GreatestPredicate : fexp.Function is LeastPredicate) {
 06789              if (Context.KNat != ((ExtremePredicate)fexp.Function).KNat) {
 06790                resolver.KNatMismatchError(expr.tok, Context.Name, Context.TypeOfK, ((ExtremePredicate)fexp.Function).Ty
 06791              } else {
 06792                friendlyCalls.Add(fexp);
 06793              }
 06794            }
 06795          }
 06796          return false;  // don't explore subexpressions any further
 06797        } else if (expr is BinaryExpr && IsCoContext) {
 06798          var bin = (BinaryExpr)expr;
 06799          if (cp == CallingPosition.Positive && bin.ResolvedOp == BinaryExpr.ResolvedOpcode.EqCommon && bin.E0.Type.IsCo
 06800            friendlyCalls.Add(bin);
 06801            return false;  // don't explore subexpressions any further
 06802          } else if (cp == CallingPosition.Negative && bin.ResolvedOp == BinaryExpr.ResolvedOpcode.NeqCommon && bin.E0.T
 06803            friendlyCalls.Add(bin);
 06804            return false;  // don't explore subexpressions any further
 6805          }
 06806        }
 06807        return base.VisitOneExpr(expr, ref cp);
 06808      }
 6809    }
 6810  }
 6811
 6812  abstract class ResolverTopDownVisitor<T> : TopDownVisitor<T> {
 6813    protected Resolver resolver;
 6814    public ResolverTopDownVisitor(Resolver resolver) {
 6815      Contract.Requires(resolver != null);
 6816      this.resolver = resolver;
 6817    }
 6818  }
 6819
 6820  class CoCallResolution {
 6821    readonly Function currentFunction;
 6822    readonly bool dealsWithCodatatypes;
 6823    public bool HasIntraClusterCallsInDestructiveContexts = false;
 6824    public readonly List<CoCallInfo> FinalCandidates = new List<CoCallInfo>();
 6825
 6826    public CoCallResolution(Function currentFunction, bool dealsWithCodatatypes) {
 6827      Contract.Requires(currentFunction != null);
 6828      this.currentFunction = currentFunction;
 6829      this.dealsWithCodatatypes = dealsWithCodatatypes;
 6830    }
 6831
 6832    /// <summary>
 6833    /// Determines which calls in "expr" can be considered to be co-calls, which co-constructor
 6834    /// invocations host such co-calls, and which destructor operations are not allowed.
 6835    /// Also records whether or not there are any intra-cluster calls in a destructive context.
 6836    /// Assumes "expr" to have been successfully resolved.
 6837    /// </summary>
 6838    public void CheckCoCalls(Expression expr) {
 6839      Contract.Requires(expr != null);
 6840      CheckCoCalls(expr, 0, null, FinalCandidates);
 6841    }
 6842
 6843    public struct CoCallInfo {
 6844      public readonly FunctionCallExpr CandidateCall;
 6845      public readonly DatatypeValue EnclosingCoConstructor;
 6846      public CoCallInfo(FunctionCallExpr candidateCall, DatatypeValue enclosingCoConstructor) {
 6847        Contract.Requires(candidateCall != null);
 6848        Contract.Requires(enclosingCoConstructor != null);
 6849        CandidateCall = candidateCall;
 6850        EnclosingCoConstructor = enclosingCoConstructor;
 6851      }
 6852    }
 6853
 6854    /// <summary>
 6855    /// Recursively goes through the entire "expr".  Every call within the same recursive cluster is a potential
 6856    /// co-call.  If the call is determined not to be a co-recursive call, then its .CoCall field is filled in;
 6857    /// if the situation deals with co-datatypes, then one of the NoBecause... values is chosen (rather
 6858    /// than just No), so that any error message that may later be produced when trying to prove termination of the
 6859    /// recursive call can include a note pointing out that the call was not selected to be a co-call.
 6860    /// If the call looks like it is guarded, then it is added to the list "coCandicates", so that a later analysis
 6861    /// can either set all of those .CoCall fields to Yes or to NoBecauseRecursiveCallsInDestructiveContext, depending
 6862    /// on other intra-cluster calls.
 6863    /// The "destructionLevel" indicates how many pending co-destructors the context has.  It may be infinity (int.MaxVa
 6864    /// if the enclosing context has no easy way of controlling the uses of "expr" (for example, if the enclosing contex
 6865    /// passes "expr" to a function or binds "expr" to a variable).  It is never negative -- excess co-constructors are
 6866    /// not considered an asset, and any immediately enclosing co-constructor is passed in as a non-null "coContext" any
 6867    /// "coContext" is non-null if the immediate context is a co-constructor.
 6868    /// </summary>
 6869    void CheckCoCalls(Expression expr, int destructionLevel, DatatypeValue coContext, List<CoCallInfo> coCandidates, Fun
 6870      Contract.Requires(expr != null);
 6871
 6872      Contract.Requires(0 <= destructionLevel);
 6873      Contract.Requires(coCandidates != null);
 6874      expr = expr.Resolved;
 6875      if (expr is DatatypeValue) {
 6876        var e = (DatatypeValue)expr;
 6877        if (e.Ctor.EnclosingDatatype is CoDatatypeDecl) {
 6878          int dl = destructionLevel == int.MaxValue ? int.MaxValue : destructionLevel == 0 ? 0 : destructionLevel - 1;
 6879          foreach (var arg in e.Arguments) {
 6880            CheckCoCalls(arg, dl, e, coCandidates);
 6881          }
 6882          return;
 6883        }
 6884      } else if (expr is MemberSelectExpr) {
 6885        var e = (MemberSelectExpr)expr;
 6886        if (e.Member.EnclosingClass is CoDatatypeDecl) {
 6887          int dl = destructionLevel == int.MaxValue ? int.MaxValue : destructionLevel + 1;
 6888          CheckCoCalls(e.Obj, dl, coContext, coCandidates);
 6889          return;
 6890        }
 6891      } else if (expr is BinaryExpr) {
 6892        var e = (BinaryExpr)expr;
 6893        if (e.ResolvedOp == BinaryExpr.ResolvedOpcode.EqCommon || e.ResolvedOp == BinaryExpr.ResolvedOpcode.NeqCommon) {
 6894          // Equality and disequality (for any type that may contain a co-datatype) are as destructive as can be--in ess
 6895          // they destruct the values indefinitely--so don't allow any co-recursive calls in the operands.
 6896          CheckCoCalls(e.E0, int.MaxValue, null, coCandidates);
 6897          CheckCoCalls(e.E1, int.MaxValue, null, coCandidates);
 6898          return;
 6899        }
 6900      } else if (expr is TernaryExpr) {
 6901        var e = (TernaryExpr)expr;
 6902        if (e.Op == TernaryExpr.Opcode.PrefixEqOp || e.Op == TernaryExpr.Opcode.PrefixNeqOp) {
 6903          // Prefix equality and disequality (for any type that may contain a co-datatype) are destructive.
 6904          CheckCoCalls(e.E0, int.MaxValue, null, coCandidates);
 6905          CheckCoCalls(e.E1, int.MaxValue, null, coCandidates);
 6906          CheckCoCalls(e.E2, int.MaxValue, null, coCandidates);
 6907          return;
 6908        }
 6909      } else if (expr is NestedMatchExpr) {
 6910        var e = (NestedMatchExpr)expr;
 6911        foreach (var child in e.SubExpressions) {
 6912          CheckCoCalls(child, destructionLevel, coContext, coCandidates);
 6913        }
 6914      } else if (expr is MatchExpr) {
 6915        var e = (MatchExpr)expr;
 6916        CheckCoCalls(e.Source, int.MaxValue, null, coCandidates);
 6917        foreach (var kase in e.Cases) {
 6918          CheckCoCalls(kase.Body, destructionLevel, coContext, coCandidates);
 6919        }
 6920        return;
 6921      } else if (expr is ITEExpr) {
 6922        var e = (ITEExpr)expr;
 6923        CheckCoCalls(e.Test, int.MaxValue, null, coCandidates);
 6924        CheckCoCalls(e.Thn, destructionLevel, coContext, coCandidates);
 6925        CheckCoCalls(e.Els, destructionLevel, coContext, coCandidates);
 6926        return;
 6927      } else if (expr is FunctionCallExpr) {
 6928        var e = (FunctionCallExpr)expr;
 6929        // First, consider the arguments of the call, making sure that they do not include calls within the recursive cl
 6930        // unless the callee is abstemious.
 6931        var abstemious = true;
 6932        if (!Attributes.ContainsBool(e.Function.Attributes, "abstemious", ref abstemious)) {
 6933          abstemious = false;
 6934        }
 6935        Contract.Assert(e.Args.Count == e.Function.Formals.Count);
 6936        for (var i = 0; i < e.Args.Count; i++) {
 6937          var arg = e.Args[i];
 6938          if (!e.Function.Formals[i].Type.IsCoDatatype) {
 6939            CheckCoCalls(arg, int.MaxValue, null, coCandidates);
 6940          } else if (abstemious) {
 6941            CheckCoCalls(arg, 0, coContext, coCandidates);
 6942          } else {
 6943            // don't you wish the callee were abstemious
 6944            CheckCoCalls(arg, int.MaxValue, null, coCandidates, e.Function);
 6945          }
 6946        }
 6947        // Second, investigate the possibility that this call itself may be a candidate co-call
 6948        if (e.Name != "requires" && ModuleDefinition.InSameSCC(currentFunction, e.Function)) {
 6949          // This call goes to another function in the same recursive cluster
 6950          if (destructionLevel != 0 && GuaranteedCoCtors(e.Function) <= destructionLevel) {
 6951            // a potentially destructive context
 6952            HasIntraClusterCallsInDestructiveContexts = true;  // this says we found an intra-cluster call unsuitable fo
 6953            if (!dealsWithCodatatypes) {
 6954              e.CoCall = FunctionCallExpr.CoCallResolution.No;
 6955            } else {
 6956              e.CoCall = FunctionCallExpr.CoCallResolution.NoBecauseRecursiveCallsAreNotAllowedInThisContext;
 6957              if (functionYouMayWishWereAbstemious != null) {
 6958                e.CoCallHint = string.Format("perhaps try declaring function '{0}' with '{{:abstemious}}'", functionYouM
 6959              }
 6960            }
 6961          } else if (coContext == null) {
 6962            // no immediately enclosing co-constructor
 6963            if (!dealsWithCodatatypes) {
 6964              e.CoCall = FunctionCallExpr.CoCallResolution.No;
 6965            } else {
 6966              e.CoCall = FunctionCallExpr.CoCallResolution.NoBecauseIsNotGuarded;
 6967            }
 6968          } else if (e.Function.Reads.Count != 0) {
 6969            // this call is disqualified from being a co-call, because of side effects
 6970            if (!dealsWithCodatatypes) {
 6971              e.CoCall = FunctionCallExpr.CoCallResolution.No;
 6972            } else {
 6973              e.CoCall = FunctionCallExpr.CoCallResolution.NoBecauseFunctionHasSideEffects;
 6974            }
 6975          } else if (e.Function.Ens.Count != 0) {
 6976            // this call is disqualified from being a co-call, because it has a postcondition
 6977            // (a postcondition could be allowed, as long as it does not get to be used with
 6978            // co-recursive calls, because that could be unsound; for example, consider
 6979            // "ensures false")
 6980            if (!dealsWithCodatatypes) {
 6981              e.CoCall = FunctionCallExpr.CoCallResolution.No;
 6982            } else {
 6983              e.CoCall = FunctionCallExpr.CoCallResolution.NoBecauseFunctionHasPostcondition;
 6984            }
 6985          } else {
 6986            // e.CoCall is not filled in here, but will be filled in when the list of candidates are processed
 6987            coCandidates.Add(new CoCallInfo(e, coContext));
 6988          }
 6989        }
 6990        return;
 6991      } else if (expr is LambdaExpr) {
 6992        var e = (LambdaExpr)expr;
 6993        CheckCoCalls(e.Term, destructionLevel, coContext, coCandidates);
 6994        if (e.Range != null) {
 6995          CheckCoCalls(e.Range, int.MaxValue, null, coCandidates);
 6996        }
 6997        foreach (var read in e.Reads) {
 6998          CheckCoCalls(read.E, int.MaxValue, null, coCandidates);
 6999        }
 7000        return;
 7001      } else if (expr is MapComprehension) {
 7002        var e = (MapComprehension)expr;
 7003        foreach (var ee in Attributes.SubExpressions(e.Attributes)) {
 7004          CheckCoCalls(ee, int.MaxValue, null, coCandidates);
 7005        }
 7006        if (e.Range != null) {
 7007          CheckCoCalls(e.Range, int.MaxValue, null, coCandidates);
 7008        }
 7009        // allow co-calls in the term
 7010        if (e.TermLeft != null) {
 7011          CheckCoCalls(e.TermLeft, destructionLevel, coContext, coCandidates);
 7012        }
 7013        CheckCoCalls(e.Term, destructionLevel, coContext, coCandidates);
 7014        return;
 7015      } else if (expr is OldExpr) {
 7016        var e = (OldExpr)expr;
 7017        // here, "coContext" is passed along (the use of "old" says this must be ghost code, so the compiler does not ne
 7018        CheckCoCalls(e.E, destructionLevel, coContext, coCandidates);
 7019        return;
 7020      } else if (expr is LetExpr) {
 7021        var e = (LetExpr)expr;
 7022        foreach (var rhs in e.RHSs) {
 7023          CheckCoCalls(rhs, int.MaxValue, null, coCandidates);
 7024        }
 7025        CheckCoCalls(e.Body, destructionLevel, coContext, coCandidates);
 7026        return;
 7027      } else if (expr is ApplyExpr) {
 7028        var e = (ApplyExpr)expr;
 7029        CheckCoCalls(e.Function, int.MaxValue, null, coCandidates);
 7030        foreach (var ee in e.Args) {
 7031          CheckCoCalls(ee, destructionLevel, null, coCandidates);
 7032        }
 7033        return;
 7034      }
 7035
 7036      // Default handling:
 7037      foreach (var ee in expr.SubExpressions) {
 7038        CheckCoCalls(ee, destructionLevel, null, coCandidates);
 7039      }
 7040    }
 7041
 7042    public static int GuaranteedCoCtors(Function function) {
 7043      Contract.Requires(function != null);
 7044      return function.Body != null ? GuaranteedCoCtorsAux(function.Body) : 0;
 7045    }
 7046
 7047    private static int GuaranteedCoCtorsAux(Expression expr) {
 7048      Contract.Requires(expr != null);
 7049      expr = expr.Resolved;
 7050      if (expr is DatatypeValue) {
 7051        var e = (DatatypeValue)expr;
 7052        if (e.Ctor.EnclosingDatatype is CoDatatypeDecl) {
 7053          var minOfArgs = int.MaxValue;  // int.MaxValue means: not yet encountered a formal whose type is a co-datatype
 7054          Contract.Assert(e.Arguments.Count == e.Ctor.Formals.Count);
 7055          for (var i = 0; i < e.Arguments.Count; i++) {
 7056            if (e.Ctor.Formals[i].Type.IsCoDatatype) {
 7057              var n = GuaranteedCoCtorsAux(e.Arguments[i]);
 7058              minOfArgs = Math.Min(minOfArgs, n);
 7059            }
 7060          }
 7061          return minOfArgs == int.MaxValue ? 1 : 1 + minOfArgs;
 7062        }
 7063      } else if (expr is ITEExpr) {
 7064        var e = (ITEExpr)expr;
 7065        var thn = GuaranteedCoCtorsAux(e.Thn);
 7066        var els = GuaranteedCoCtorsAux(e.Els);
 7067        return thn < els ? thn : els;
 7068      } else if (expr is NestedMatchExpr nestedMatchExpr) {
 7069        var childValues = nestedMatchExpr.Cases.Select(child => GuaranteedCoCtorsAux(child.Body)).ToList();
 7070        return childValues.Any() ? childValues.Min() : 0;
 7071      } else if (expr is MatchExpr) {
 7072        var e = (MatchExpr)expr;
 7073        var min = int.MaxValue;
 7074        foreach (var kase in e.Cases) {
 7075          var n = GuaranteedCoCtorsAux(kase.Body);
 7076          min = Math.Min(min, n);
 7077        }
 7078        return min == int.MaxValue ? 0 : min;
 7079      } else if (expr is LetExpr) {
 7080        var e = (LetExpr)expr;
 7081        return GuaranteedCoCtorsAux(e.Body);
 7082      } else if (expr is IdentifierExpr) {
 7083        var e = (IdentifierExpr)expr;
 7084        if (e.Type.IsCoDatatype && e.Var is Formal) {
 7085          // even though this is not a co-constructor, count this as 1, since that's what we would have done if it were,
 7086          return 1;
 7087        }
 7088      }
 7089      return 0;
 7090    }
 7091  }
 7092}

/home/ubuntu/dafny-verifier/src/main/dafny_compiler/dafny/Source/DafnyCore/Resolver/TypeInferenceChecker.cs

#LineLine coverage
 1using System.Collections.Generic;
 2using System.Diagnostics.Contracts;
 3using System.Linq;
 4using System.Numerics;
 5using Microsoft.Boogie;
 6using static Microsoft.Dafny.ErrorRegistry;
 7
 8namespace Microsoft.Dafny;
 9
 10partial class Resolver {
 11  class TypeInferenceCheckingContext : IASTVisitorContext {
 12    private readonly IASTVisitorContext astVisitorContext;
 13
 219214    public bool IsPrefixPredicate => astVisitorContext is PrefixPredicate;
 015    public bool IsExtremePredicate => astVisitorContext is ExtremePredicate;
 5071716    public bool IsPrefixDeclaration => astVisitorContext is PrefixPredicate or PrefixLemma;
 17
 640618    public TypeInferenceCheckingContext(IASTVisitorContext astVisitorContext) {
 320319      this.astVisitorContext = astVisitorContext;
 320320    }
 21
 218022    ModuleDefinition IASTVisitorContext.EnclosingModule => astVisitorContext.EnclosingModule;
 23  }
 24
 25  class CheckTypeInferenceVisitor : ASTVisitor<TypeInferenceCheckingContext> {
 26    private readonly Resolver resolver;
 027    private ErrorReporter reporter => resolver.reporter;
 28
 65229    public CheckTypeInferenceVisitor(Resolver resolver) {
 32630      this.resolver = resolver;
 32631    }
 32
 320333    public override TypeInferenceCheckingContext GetContext(IASTVisitorContext astVisitorContext, bool inFunctionPostcon
 320334      return new TypeInferenceCheckingContext(astVisitorContext);
 320335    }
 36
 93137    protected override void VisitOneDeclaration(TopLevelDecl decl) {
 93138      if (decl is NewtypeDecl newtypeDecl) {
 039        if (newtypeDecl.Var != null) {
 040          if (!IsDetermined(newtypeDecl.BaseType.NormalizeExpand())) {
 041            reporter.Error(MessageSource.Resolver, newtypeDecl.tok, "newtype's base type is not fully determined; add an
 042              newtypeDecl.Var.Name);
 043          }
 044        }
 45
 115546      } else if (decl is SubsetTypeDecl subsetTypeDecl) {
 22447        if (!IsDetermined(subsetTypeDecl.Rhs.NormalizeExpand())) {
 048          reporter.Error(MessageSource.Resolver, subsetTypeDecl.tok,
 049            "subset type's base type is not fully determined; add an explicit type for '{0}'", subsetTypeDecl.Var.Name);
 050        }
 51
 120052      } else if (decl is DatatypeDecl datatypeDecl) {
 435953        foreach (var member in resolver.classMembers[datatypeDecl].Values) {
 177454          if (member is DatatypeDestructor dtor) {
 59055            var rolemodel = dtor.CorrespondingFormals[0];
 118056            for (var i = 1; i < dtor.CorrespondingFormals.Count; i++) {
 057              var other = dtor.CorrespondingFormals[i];
 058              if (!Type.Equal_Improved(rolemodel.Type, other.Type)) {
 059                reporter.Error(MessageSource.Resolver, other,
 060                  "shared destructors must have the same type, but '{0}' has type '{1}' in constructor '{2}' and type '{
 061                  rolemodel.Name, rolemodel.Type, dtor.EnclosingCtors[0].Name, other.Type, dtor.EnclosingCtors[i].Name);
 062              }
 063            }
 59064          }
 118465        }
 26966      }
 67
 93168      base.VisitOneDeclaration(decl);
 93169    }
 70
 11271    public override void VisitField(Field field) {
 11272      if (field is ConstantField constantField) {
 073        resolver.PartiallySolveTypeConstraints(true);
 074        CheckTypeIsDetermined(field.tok, field.Type, "const");
 075      }
 76
 11277      base.VisitField(field);
 11278    }
 79
 16882280    protected override bool VisitOneStatement(Statement stmt, TypeInferenceCheckingContext context) {
 16882281      if (stmt is CalcStmt calcStmt) {
 82        // The resolution of the calc statement builds up .Steps and .Result, which are of the form E0 OP E1, where
 83        // E0 and E1 are expressions from .Lines.  These additional expressions still need to have their .ResolvedOp
 84        // fields filled in, so we visit them, rather than just the parsed .Lines.
 085        Attributes.SubExpressions(calcStmt.Attributes).Iter(e => VisitExpression(e, context));
 086        calcStmt.Steps.Iter(e => VisitExpression(e, context));
 087        VisitExpression(calcStmt.Result, context);
 088        calcStmt.Hints.Iter(hint => VisitStatement(hint, context));
 089        return false; // we're done with all subcomponents of the CalcStmt
 90      }
 91
 16882292      return base.VisitOneStatement(stmt, context);
 16882293    }
 94
 16882295    protected override void PostVisitOneStatement(Statement stmt, TypeInferenceCheckingContext context) {
 21769696      if (stmt is VarDeclStmt) {
 4887497        var s = (VarDeclStmt)stmt;
 29877398        foreach (var local in s.Locals) {
 5071799          CheckTypeIsDetermined(local.Tok, local.Type, "local variable");
 50717100          CheckTypeArgsContainNoOrdinal(local.Tok, local.type, context);
 50717101        }
 168822102      } else if (stmt is VarDeclPattern) {
 0103        var s = (VarDeclPattern)stmt;
 0104        s.LocalVars.Iter(local => CheckTypeIsDetermined(local.Tok, local.Type, "local variable"));
 0105        s.LocalVars.Iter(local => CheckTypeArgsContainNoOrdinal(local.Tok, local.Type, context));
 106
 119948107      } else if (stmt is ForallStmt) {
 0108        var s = (ForallStmt)stmt;
 0109        s.BoundVars.Iter(bv => CheckTypeIsDetermined(bv.tok, bv.Type, "bound variable"));
 0110        s.BoundVars.Iter(bv => CheckTypeArgsContainNoOrdinal(bv.tok, bv.Type, context));
 111
 119948112      } else if (stmt is AssignSuchThatStmt) {
 0113        var s = (AssignSuchThatStmt)stmt;
 0114        foreach (var lhs in s.Lhss) {
 0115          CheckTypeArgsContainNoOrdinal(lhs.tok, lhs.Type, context);
 0116        }
 0117      }
 118
 168822119      base.PostVisitOneStatement(stmt, context);
 168822120    }
 121
 807528122    protected override void PostVisitOneExpression(Expression expr, TypeInferenceCheckingContext context) {
 1051841123      if (expr is LiteralExpr) {
 244313124        var e = (LiteralExpr)expr;
 244313125        if (e.Type.IsBitVectorType || e.Type.IsBigOrdinalType) {
 0126          var n = (BigInteger)e.Value;
 0127          var absN = n < 0 ? -n : n;
 128          // For bitvectors, check that the magnitude fits the width
 0129          if (e.Type.IsBitVectorType && MaxBV(e.Type.AsBitVectorType.Width) < absN) {
 0130            resolver.reporter.Error(MessageSource.Resolver, e.tok, "literal ({0}) is too large for the bitvector type {1
 0131          }
 132          // For bitvectors and ORDINALs, check for a unary minus that, earlier, was mistaken for a negative literal
 133          // This can happen only in `match` patterns (see comment by LitPattern.OptimisticallyDesugaredLit).
 0134          if (n < 0 || e.tok.val == "-0") {
 0135            Contract.Assert(e.tok.val == "-0");  // this and the "if" above tests that "n < 0" happens only when the tok
 0136            resolver.reporter.Error(MessageSource.Resolver, e.tok, "unary minus (-{0}, type {1}) not allowed in case pat
 0137          }
 0138        }
 139
 247784140        if (expr is StaticReceiverExpr stexpr) {
 10413141          foreach (Type t in stexpr.Type.TypeArgs) {
 0142            if (t is InferredTypeProxy && ((InferredTypeProxy)t).T == null) {
 0143              resolver.reporter.Error(MessageSource.Resolver, stexpr.tok, "type of type parameter could not be determine
 0144            }
 0145          }
 3471146        }
 147
 807528148      } else if (expr is ComprehensionExpr) {
 0149        var e = (ComprehensionExpr)expr;
 0150        foreach (var bv in e.BoundVars) {
 0151          if (!IsDetermined(bv.Type.Normalize())) {
 0152            resolver.reporter.Error(MessageSource.Resolver, bv.tok,
 0153              $"type of bound variable '{bv.Name}' could not be determined; please specify the type explicitly");
 0154          } else if (context.IsExtremePredicate) {
 0155            CheckContainsNoOrdinal(bv.tok, bv.Type, $"type of bound variable '{bv.Name}' ('{bv.Type}') is not allowed to
 0156          }
 0157        }
 158
 0159        if (e is ExistsExpr && e.Range == null) {
 0160          var binBody = ((ExistsExpr)e).Term as BinaryExpr;
 0161          if (binBody != null && binBody.Op == BinaryExpr.Opcode.Imp) {  // check Op, not ResolvedOp, in order to distin
 162                                                                         // apply the wisdom of Claude Marche: issue a w
 0163            resolver.reporter.Warning(MessageSource.Resolver, ErrorRegistry.NoneId, e.tok,
 0164              "the quantifier has the form 'exists x :: A ==> B', which most often is a typo for 'exists x :: A && B'; "
 0165              "if you think otherwise, rewrite as 'exists x :: (A ==> B)' or 'exists x :: !A || B' to suppress this warn
 0166          }
 0167        }
 168
 574895169      } else if (expr is MemberSelectExpr) {
 11680170        var e = (MemberSelectExpr)expr;
 15151171        if (e.Member is Function || e.Member is Method) {
 3471172          var i = 0;
 16989173          foreach (var p in Util.Concat(e.TypeApplication_AtEnclosingClass, e.TypeApplication_JustMember)) {
 2192174            var tp = i < e.TypeApplication_AtEnclosingClass.Count
 2192175              ? e.Member.EnclosingClass.TypeArgs[i]
 2192176              : ((ICallable)e.Member).TypeArgs[i - e.TypeApplication_AtEnclosingClass.Count];
 2192177            if (!IsDetermined(p.Normalize())) {
 0178              resolver.reporter.Error(MessageSource.Resolver, e.tok,
 0179                $"type parameter '{tp.Name}' (inferred to be '{p}') to the {e.Member.WhatKind} '{e.Member.Name}' could n
 4384180            } else if (!context.IsPrefixPredicate) { // this check is done in extreme predicates, so no need to repeat i
 2192181              CheckContainsNoOrdinal(e.tok, p,
 2192182                $"type parameter '{tp.Name}' (passed in as '{p}') to the {e.Member.WhatKind} '{e.Member.Name}' is not al
 2192183            }
 2192184            i++;
 2192185          }
 3471186        }
 563215187      } else if (expr is FunctionCallExpr) {
 0188        var e = (FunctionCallExpr)expr;
 0189        var i = 0;
 0190        foreach (var p in Util.Concat(e.TypeApplication_AtEnclosingClass, e.TypeApplication_JustFunction)) {
 0191          var tp = i < e.TypeApplication_AtEnclosingClass.Count
 0192            ? e.Function.EnclosingClass.TypeArgs[i]
 0193            : e.Function.TypeArgs[i - e.TypeApplication_AtEnclosingClass.Count];
 0194          if (!IsDetermined(p.Normalize())) {
 0195            var hint = e.Name.StartsWith("reveal_")
 0196              ? ". If you are making an opaque function, make sure that the function can be called."
 0197              : "";
 0198            resolver.reporter.Error(MessageSource.Resolver, e.tok,
 0199              $"type parameter '{tp.Name}' (inferred to be '{p}') in the function call to '{e.Name}' could not be determ
 0200          } else if (!context.IsPrefixPredicate) { // this check is done in extreme predicates, so no need to repeat it 
 0201            CheckContainsNoOrdinal(e.tok, p,
 0202              $"type parameter '{tp.Name}' (passed in as '{p}') to function call '{e.Name}' is not allowed to use ORDINA
 0203          }
 0204          i++;
 0205        }
 551535206      } else if (expr is LetExpr) {
 0207        var e = (LetExpr)expr;
 0208        foreach (var p in e.LHSs) {
 0209          foreach (var x in p.Vars) {
 0210            if (!IsDetermined(x.Type.Normalize())) {
 0211              resolver.reporter.Error(MessageSource.Resolver, x.tok, $"the type of the bound variable '{x.Name}' could n
 0212            } else {
 0213              CheckTypeArgsContainNoOrdinal(x.tok, x.Type, context);
 0214            }
 0215          }
 0216        }
 734741217      } else if (expr is IdentifierExpr) {
 218        // by specializing for IdentifierExpr, error messages will be clearer
 183206219        CheckTypeIsDetermined(expr.tok, expr.Type, "variable");
 551535220      } else if (expr is ConversionExpr) {
 0221        var e = (ConversionExpr)expr;
 0222        if (e.ToType.IsRefType) {
 0223          var fromType = e.E.Type;
 0224          Contract.Assert(fromType.IsRefType);
 0225          if (fromType.IsSubtypeOf(e.ToType, false, true) || e.ToType.IsSubtypeOf(fromType, false, true)) {
 226            // looks good
 0227          } else {
 0228            resolver.reporter.Error(MessageSource.Resolver, e.tok,
 0229              "a type cast to a reference type ({0}) must be from a compatible type (got {1}); this cast could never suc
 0230              e.ToType, fromType);
 0231          }
 0232        }
 368329233      } else if (expr is TypeTestExpr) {
 0234        var e = (TypeTestExpr)expr;
 0235        var fromType = e.E.Type;
 0236        if (fromType.IsSubtypeOf(e.ToType, false, true)) {
 237          // This test is allowed and it always returns true
 0238        } else if (!e.ToType.IsSubtypeOf(fromType, false, true)) {
 0239          resolver.reporter.Error(MessageSource.Resolver, e.tok,
 0240            "a type test to '{0}' must be from a compatible type (got '{1}')", e.ToType, fromType);
 0241        } else if (!e.ToType.IsRefType) {
 0242          resolver.reporter.Error(MessageSource.Resolver, e.tok,
 0243            "a non-trivial type test is allowed only for reference types (tried to test if '{1}' is a '{0}')", e.ToType,
 0244        }
 736638245      } else if (CheckTypeIsDetermined(expr.tok, expr.Type, "expression")) {
 377554246        if (expr is UnaryOpExpr uop) {
 247          // The CheckTypeInference_Visitor has already visited uop.E, but uop.E's may be undetermined. If that happened
 248          // then an error has already been reported.
 18485249          if (CheckTypeIsDetermined(uop.E.tok, uop.E.Type, "expression")) {
 9240250            uop.ResolveOp(); // Force resolution eagerly at this point to catch potential bugs
 9240251          }
 432797252        } else if (expr is BinaryExpr) {
 64488253          var e = (BinaryExpr)expr;
 64488254          e.ResolvedOp = ResolveOp(e.Op, e.E0.Type, e.E1.Type);
 255          // Check for useless comparisons with "null"
 64488256          Expression other = null;  // if "null" if one of the operands, then "other" is the other
 64488257          if (e.E0 is LiteralExpr && ((LiteralExpr)e.E0).Value == null) {
 0258            other = e.E1;
 64712259          } else if (e.E1 is LiteralExpr && ((LiteralExpr)e.E1).Value == null) {
 224260            other = e.E0;
 224261          }
 64712262          if (other != null) {
 224263            bool sense = true;
 224264            switch (e.ResolvedOp) {
 265              case BinaryExpr.ResolvedOpcode.NeqCommon:
 224266                sense = false;
 224267                goto case BinaryExpr.ResolvedOpcode.EqCommon;
 224268              case BinaryExpr.ResolvedOpcode.EqCommon: {
 224269                  var nntUdf = other.Type.AsNonNullRefType;
 224270                  if (nntUdf != null) {
 0271                    string name = null;
 0272                    string hint = "";
 0273                    other = other.Resolved;
 0274                    if (other is IdentifierExpr) {
 0275                      name = $"variable '{((IdentifierExpr)other).Name}'";
 0276                    } else if (other is MemberSelectExpr) {
 0277                      var field = ((MemberSelectExpr)other).Member as Field;
 278                      // The type of the field may be a formal type parameter, in which case the hint is omitted
 0279                      if (field.Type.IsNonNullRefType) {
 0280                        name = $"field '{field.Name}'";
 0281                      }
 0282                    }
 0283                    if (name != null) {
 284                      // The following relies on that a NonNullTypeDecl has a .Rhs that is a
 285                      // UserDefinedType denoting the possibly null type declaration and that
 286                      // these two types have the same number of type arguments.
 0287                      var nonNullTypeDecl = (NonNullTypeDecl)nntUdf.ResolvedClass;
 0288                      var possiblyNullUdf = (UserDefinedType)nonNullTypeDecl.Rhs;
 0289                      var possiblyNullTypeDecl = (ClassDecl)possiblyNullUdf.ResolvedClass;
 0290                      Contract.Assert(nonNullTypeDecl.TypeArgs.Count == possiblyNullTypeDecl.TypeArgs.Count);
 0291                      Contract.Assert(nonNullTypeDecl.TypeArgs.Count == nntUdf.TypeArgs.Count);
 0292                      var ty = new UserDefinedType(nntUdf.tok, possiblyNullUdf.Name, possiblyNullTypeDecl, nntUdf.TypeAr
 293
 0294                      hint = $" (to make it possible for {name} to have the value 'null', declare its type to be '{ty}')
 0295                    }
 0296                    var b = sense ? "false" : "true";
 0297                    resolver.reporter.Warning(MessageSource.Resolver, ErrorRegistry.NoneId, e.tok,
 0298                      $"the type of the other operand is a non-null type, so this comparison with 'null' will always ret
 0299                  }
 224300                  break;
 301                }
 302              case BinaryExpr.ResolvedOpcode.NotInSet:
 303              case BinaryExpr.ResolvedOpcode.NotInSeq:
 304              case BinaryExpr.ResolvedOpcode.NotInMultiSet:
 0305                sense = false;
 0306                goto case BinaryExpr.ResolvedOpcode.InSet;
 307              case BinaryExpr.ResolvedOpcode.InSet:
 308              case BinaryExpr.ResolvedOpcode.InSeq:
 0309              case BinaryExpr.ResolvedOpcode.InMultiSet: {
 0310                  var ty = other.Type.NormalizeExpand();
 0311                  var what = ty is SetType ? "set" : ty is SeqType ? "seq" : "multiset";
 0312                  if (((CollectionType)ty).Arg.IsNonNullRefType) {
 0313                    var non = sense ? "" : "non-";
 0314                    var b = sense ? "false" : "true";
 0315                    resolver.reporter.Warning(MessageSource.Resolver, ErrorRegistry.NoneId, e.tok,
 0316                      $"the type of the other operand is a {what} of non-null elements, so the {non}inclusion test of 'n
 0317                  }
 0318                  break;
 319                }
 320              case BinaryExpr.ResolvedOpcode.NotInMap:
 0321                goto case BinaryExpr.ResolvedOpcode.InMap;
 0322              case BinaryExpr.ResolvedOpcode.InMap: {
 0323                  var ty = other.Type.NormalizeExpand();
 0324                  if (((MapType)ty).Domain.IsNonNullRefType) {
 0325                    var b = sense ? "false" : "true";
 0326                    resolver.reporter.Warning(MessageSource.Resolver, ErrorRegistry.NoneId, e.tok,
 0327                      $"the type of the other operand is a map to a non-null type, so the inclusion test of 'null' will 
 0328                  }
 0329                  break;
 330                }
 331              default:
 0332                break;
 333            }
 224334          }
 374594335        } else if (expr is NegationExpression) {
 15530336          var e = (NegationExpression)expr;
 15530337          Expression resolved = null;
 31060338          if (e.E is LiteralExpr lit) { // note, not e.E.Resolved, since we don't want to do this for double negations
 339                                        // For real-based types, integer-based types, and bi (but not bitvectors), "-" f
 340                                        // just a literal expression with a negative value
 26095341            if (e.E.Type.IsNumericBased(Type.NumericPersuasion.Real)) {
 10565342              var d = (BaseTypes.BigDec)lit.Value;
 10565343              Contract.Assert(!d.IsNegative);
 10565344              resolved = new LiteralExpr(e.tok, -d);
 20495345            } else if (e.E.Type.IsNumericBased(Type.NumericPersuasion.Int)) {
 4965346              var n = (BigInteger)lit.Value;
 4965347              Contract.Assert(0 <= n);
 4965348              resolved = new LiteralExpr(e.tok, -n);
 4965349            }
 15530350          }
 15530351          if (resolved == null) {
 352            // Treat all other expressions "-e" as "0 - e"
 353            Expression zero;
 0354            if (e.E.Type.IsNumericBased(Type.NumericPersuasion.Real)) {
 0355              zero = new LiteralExpr(e.tok, BaseTypes.BigDec.ZERO);
 0356            } else {
 0357              Contract.Assert(e.E.Type.IsNumericBased(Type.NumericPersuasion.Int) || e.E.Type.IsBitVectorType);
 0358              zero = new LiteralExpr(e.tok, 0);
 0359            }
 0360            zero.Type = expr.Type;
 0361            resolved = new BinaryExpr(e.tok, BinaryExpr.Opcode.Sub, zero, e.E) { ResolvedOp = BinaryExpr.ResolvedOpcode.
 0362          }
 15530363          resolved.Type = expr.Type;
 15530364          e.ResolvedExpression = resolved;
 15530365        }
 368309366      }
 367
 807528368      base.PostVisitOneExpression(expr, context);
 807528369    }
 370
 4378371    protected override void VisitExtendedPattern(ExtendedPattern pattern, TypeInferenceCheckingContext context) {
 4378372      base.VisitExtendedPattern(pattern, context);
 373
 7907374      if (pattern is IdPattern { BoundVar: { } bv }) {
 3529375        CheckTypeIsDetermined(bv.Tok, bv.Type, "bound variable");
 3529376      }
 4378377    }
 378
 4836124379    public static bool IsDetermined(Type t) {
 380      Contract.Requires(t != null);
 381      Contract.Requires(!(t is TypeProxy) || ((TypeProxy)t).T == null);
 382      // all other proxies indicate the type has not yet been determined, provided their type parameters have been
 5003710383      return !(t is TypeProxy) && t.TypeArgs.All(tt => IsDetermined(tt.Normalize()));
 4836124384    }
 385
 326386    readonly ISet<TypeProxy> UnderspecifiedTypeProxies = new HashSet<TypeProxy>();
 387
 1090389388    public bool CheckTypeIsDetermined(IToken tok, Type t, string what) {
 389      Contract.Requires(tok != null);
 390      Contract.Requires(t != null);
 391      Contract.Requires(what != null);
 1090389392      t = t.NormalizeExpandKeepConstraints();
 393
 1090414394      if (t is TypeProxy) {
 25395        var proxy = (TypeProxy)t;
 35396        if (!UnderspecifiedTypeProxies.Contains(proxy)) {
 397          // report an error for this TypeProxy only once
 10398          resolver.reporter.Error(MessageSource.Resolver, tok, "the type of this {0} is underspecified", what);
 10399          UnderspecifiedTypeProxies.Add(proxy);
 10400        }
 25401        return false;
 402      }
 403      // Recurse on type arguments:
 1565727404      return t.TypeArgs.All(rg => CheckTypeIsDetermined(tok, rg, what));
 1090389405    }
 406
 50717407    public void CheckTypeArgsContainNoOrdinal(IToken tok, Type t, TypeInferenceCheckingContext context) {
 408      Contract.Requires(tok != null);
 409      Contract.Requires(t != null);
 50717410      if (context.IsPrefixDeclaration) {
 411        // User-provided expressions in extreme predicates/lemmas are checked in the extreme declarations, so need
 412        // need to do them here again for the prefix predicates/lemmas.
 50717413      } else {
 50717414        t = t.NormalizeExpand();
 94478415        t.TypeArgs.Iter(rg => CheckContainsNoOrdinal(tok, rg, "an ORDINAL type is not allowed to be used as a type argum
 50717416      }
 50717417    }
 418
 58671419    public void CheckContainsNoOrdinal(IToken tok, Type t, string errMsg) {
 420      Contract.Requires(tok != null);
 421      Contract.Requires(t != null);
 422      Contract.Requires(errMsg != null);
 58671423      t = t.NormalizeExpand();
 58671424      if (t.IsBigOrdinalType) {
 0425        resolver.reporter.Error(MessageSource.Resolver, tok, errMsg);
 0426      }
 71389427      t.TypeArgs.Iter(rg => CheckContainsNoOrdinal(tok, rg, errMsg));
 58671428    }
 429  }
 430}

Methods/Properties

get_AllowedToDependOnAllocationState()
get_Kind()
.ctor(Microsoft.Dafny.IASTVisitorContext)
.ctor(Microsoft.Dafny.Resolver/BoundsDiscoveryVisitor/BoundsDiscoveryContext,Microsoft.Dafny.LambdaExpr)
Microsoft.Dafny.IASTVisitorContext.get_EnclosingModule()
.ctor(Microsoft.Dafny.ErrorReporter)
GetContext(Microsoft.Dafny.IASTVisitorContext,System.Boolean)
VisitOneStatement(Microsoft.Dafny.Statement,Microsoft.Dafny.Resolver/BoundsDiscoveryVisitor/BoundsDiscoveryContext)
VisitTopLevelFrameExpression(Microsoft.Dafny.FrameExpression,Microsoft.Dafny.Resolver/BoundsDiscoveryVisitor/BoundsDiscoveryContext)
DesugarFunctionsInFrameClause(Microsoft.Dafny.FrameExpression)
FrameArrowToObjectSet(Microsoft.Dafny.Expression)
VisitExpression(Microsoft.Dafny.Expression,Microsoft.Dafny.Resolver/BoundsDiscoveryVisitor/BoundsDiscoveryContext)
VisitOneExpression(Microsoft.Dafny.Expression,Microsoft.Dafny.Resolver/BoundsDiscoveryVisitor/BoundsDiscoveryContext)
DiscoverBestBounds_MultipleVars(System.Collections.Generic.List`1<VT>,Microsoft.Dafny.Expression,System.Boolean)
DiscoverBestBounds_MultipleVars_AllowReordering(System.Collections.Generic.List`1<VT>,Microsoft.Dafny.Expression,System.Boolean)
DiscoverAllBounds_Aux_MultipleVars(System.Collections.Generic.List`1<VT>,Microsoft.Dafny.Expression,System.Boolean)
DiscoverAllBounds_SingleVar(VT,Microsoft.Dafny.Expression)
DiscoverAllBounds_Aux_SingleVar(System.Collections.Generic.List`1<VT>,System.Int32,Microsoft.Dafny.Expression,System.Boolean,System.Collections.Generic.List`1<Microsoft.Dafny.ComprehensionExpr/BoundedPool>)
DiscoverBoundsFunctionCallExpr(Microsoft.Dafny.FunctionCallExpr,VT,System.Collections.Generic.List`1<Microsoft.Dafny.ComprehensionExpr/BoundedPool>)
NormalizedConjuncts()
SanitizeForBoundDiscovery(System.Collections.Generic.List`1<VT>,System.Int32,Microsoft.Dafny.BinaryExpr/ResolvedOpcode,System.Collections.Generic.List`1<Microsoft.Dafny.ComprehensionExpr/BoundedPool>,Microsoft.Dafny.Expression&,Microsoft.Dafny.Expression&)
IsMonotonic(Microsoft.Dafny.Expression,Microsoft.Dafny.IVariable,System.Boolean)
ResolveNamesAndInferTypes(System.Collections.Generic.List`1<Microsoft.Dafny.TopLevelDecl>,System.Boolean)
ResolveNamesAndInferTypesForOneDeclarationInitial(Microsoft.Dafny.TopLevelDecl)
ResolveNamesAndInferTypesForOneDeclaration(Microsoft.Dafny.TopLevelDecl)
EagerAddAssignableConstraint(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,Microsoft.Dafny.Type,System.String)
AddAssignableConstraint(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,Microsoft.Dafny.Type,System.String)
AddXConstraint(Microsoft.Dafny.IToken,System.String,Microsoft.Dafny.Type,System.String)
AddAssignableConstraint(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,Microsoft.Dafny.Type,Microsoft.Dafny.TypeConstraint/ErrorMsg)
AddXConstraint(Microsoft.Dafny.IToken,System.String,Microsoft.Dafny.Type,Microsoft.Dafny.TypeConstraint/ErrorMsg)
AddXConstraint(Microsoft.Dafny.IToken,System.String,Microsoft.Dafny.Type,Microsoft.Dafny.Type,System.String)
AddXConstraint(Microsoft.Dafny.IToken,System.String,Microsoft.Dafny.Type,Microsoft.Dafny.Type,Microsoft.Dafny.TypeConstraint/ErrorMsg)
AddXConstraint(Microsoft.Dafny.IToken,System.String,Microsoft.Dafny.Type,Microsoft.Dafny.Expression,Microsoft.Dafny.Expression,System.String)
PrintTypeConstraintState(System.Int32)
SolveAllTypeConstraints()
ResolveAttributes(Microsoft.Dafny.IAttributeBearingDeclaration,Microsoft.Dafny.ResolutionContext,System.Boolean)
ResolveExpression(Microsoft.Dafny.Expression,Microsoft.Dafny.ResolutionContext)
ResolveTypeParameters(System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>,System.Boolean,Microsoft.Dafny.TypeParameter/ParentType)
ConstrainSubtypeRelation(Microsoft.Dafny.Type,Microsoft.Dafny.Type,Microsoft.Dafny.Expression,System.String,System.Object[])
ConstrainTypeExprBool(Microsoft.Dafny.Expression,System.String)
ConstrainSubtypeRelation(Microsoft.Dafny.Type,Microsoft.Dafny.Type,Microsoft.Dafny.IToken,System.String,System.Object[])
ConstrainAssignable(Microsoft.Dafny.NonProxyType,Microsoft.Dafny.Type,Microsoft.Dafny.TypeConstraint/ErrorMsg,System.Boolean&,System.Boolean)
ConstrainAssignableTypeArgs(Microsoft.Dafny.Type,System.Collections.Generic.List`1<Microsoft.Dafny.Type>,System.Collections.Generic.List`1<Microsoft.Dafny.Type>,Microsoft.Dafny.TypeConstraint/ErrorMsg,System.Boolean&)
ConstrainSubtypeRelation_Equal(Microsoft.Dafny.Type,Microsoft.Dafny.Type,Microsoft.Dafny.TypeConstraint/ErrorMsg)
ConstrainSubtypeRelation(Microsoft.Dafny.Type,Microsoft.Dafny.Type,Microsoft.Dafny.TypeConstraint/ErrorMsg,System.Boolean,System.Boolean)
ConstrainSubtypeRelation_Aux(Microsoft.Dafny.Type,Microsoft.Dafny.Type,Microsoft.Dafny.TypeConstraint,System.Boolean,System.Boolean)
DetermineRootLeaf(Microsoft.Dafny.Type,System.Boolean&,System.Boolean&,System.Boolean&,System.Boolean&)
.ctor(Microsoft.Dafny.DafnyOptions)
AssignProxyAndHandleItsConstraints(Microsoft.Dafny.TypeProxy,Microsoft.Dafny.Type,System.Boolean)
AssignProxyAndHandleItsConstraints_aux(Microsoft.Dafny.TypeProxy,Microsoft.Dafny.Type,System.Boolean)
ImposeSubtypingConstraint(Microsoft.Dafny.Type,Microsoft.Dafny.Type,Microsoft.Dafny.TypeConstraint/ErrorMsg)
ConstrainTypeHead_Recursive(Microsoft.Dafny.Type,Microsoft.Dafny.Type&)
ConstrainTypeHead(Microsoft.Dafny.Type,Microsoft.Dafny.Type)
KeepConstraints(Microsoft.Dafny.Type,Microsoft.Dafny.Type)
.ctor(Microsoft.Dafny.IToken,System.String,Microsoft.Dafny.Type[],Microsoft.Dafny.TypeConstraint/ErrorMsg)
ToString()
Confirm(Microsoft.Dafny.Resolver,System.Boolean,System.Boolean&,System.Boolean&)
ProxyWithNoSubTypeConstraint(Microsoft.Dafny.Type,Microsoft.Dafny.Resolver)
CouldBeAnything()
FindCollectionType(Microsoft.Dafny.DafnyOptions,Microsoft.Dafny.Type,System.Boolean,System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>)
.ctor(Microsoft.Dafny.IToken,System.String,Microsoft.Dafny.Type[],Microsoft.Dafny.Expression[],Microsoft.Dafny.TypeConstraint/ErrorMsg)
.ctor(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,Microsoft.Dafny.Type,System.Boolean,System.Boolean,Microsoft.Dafny.TypeConstraint/ErrorMsg)
PartiallySolveTypeConstraints(System.Boolean)
NewIntegerBasedProxy(Microsoft.Dafny.IToken)
ContainsAsTypeParameter(Microsoft.Dafny.Type,Microsoft.Dafny.Type)
AddAllProxies(Microsoft.Dafny.Type,System.Collections.Generic.HashSet`1<Microsoft.Dafny.TypeProxy>)
ProcessAssignable(Microsoft.Dafny.TypeProxy,System.Collections.Generic.List`1<Microsoft.Dafny.Type>)
ConvertAssignableToSubtypeConstraints(System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>)
TightenUpEquatable(System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>)
ProcessOneSubtypingConstraintAndItsSubs(Microsoft.Dafny.TypeConstraint,System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeConstraint>,System.Boolean,System.Boolean&)
ProcessFullStrength_SubDirection(Microsoft.Dafny.Type,System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>,System.Boolean&)
ProcessFullStrength_SuperDirection(Microsoft.Dafny.Type,System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>,System.Boolean&)
AssignKnownEnd(Microsoft.Dafny.TypeProxy,System.Boolean,System.Boolean)
AssignKnownEndsFullstrength(Microsoft.Dafny.TypeProxy)
AssignKnownEndsFullstrength_SubDirection(Microsoft.Dafny.TypeProxy)
CloseOverAssignableRhss(System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>)
HasApplicableNullableRefTypeConstraint(System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>)
HasApplicableNullableRefTypeConstraint_SubDirection(Microsoft.Dafny.TypeProxy)
HasApplicableNullableRefTypeConstraint_SubDirection_aux(Microsoft.Dafny.TypeProxy,System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>,System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>)
AssignKnownEndsFullstrength_SuperDirection(Microsoft.Dafny.TypeProxy)
Reaches(Microsoft.Dafny.Type,Microsoft.Dafny.TypeProxy,System.Int32,System.Collections.Generic.HashSet`1<Microsoft.Dafny.TypeProxy>)
Reaches_aux(Microsoft.Dafny.Type,Microsoft.Dafny.TypeProxy,System.Int32,System.Collections.Generic.HashSet`1<Microsoft.Dafny.TypeProxy>)
ResolveClassMemberBodiesInitial(Microsoft.Dafny.TopLevelDeclWithMembers)
ResolveClassMemberBodies(Microsoft.Dafny.TopLevelDeclWithMembers)
ResolveCtorTypes(Microsoft.Dafny.DatatypeDecl,Microsoft.Dafny.Graph`1<Microsoft.Dafny.IndDatatypeDecl>,Microsoft.Dafny.Graph`1<Microsoft.Dafny.CoDatatypeDecl>)
ResolveCtorSignature(Microsoft.Dafny.DatatypeCtor,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>)
AddDatatypeDependencyEdge(Microsoft.Dafny.IndDatatypeDecl,Microsoft.Dafny.Type,Microsoft.Dafny.Graph`1<Microsoft.Dafny.IndDatatypeDecl>)
ResolveFrameExpressionTopLevel(Microsoft.Dafny.FrameExpression,Microsoft.Dafny.FrameExpressionUse,Microsoft.Dafny.ICodeContext)
ResolveFrameExpression(Microsoft.Dafny.FrameExpression,Microsoft.Dafny.FrameExpressionUse,Microsoft.Dafny.ResolutionContext)
ResolveIterator(Microsoft.Dafny.IteratorDecl)
CheckIsLvalue(Microsoft.Dafny.Expression,Microsoft.Dafny.ResolutionContext)
ResolveBlockStatement(Microsoft.Dafny.BlockStmt,Microsoft.Dafny.ResolutionContext)
ResolveStatementWithLabels(Microsoft.Dafny.Statement,Microsoft.Dafny.ResolutionContext)
ResolveAlternatives(System.Collections.Generic.List`1<Microsoft.Dafny.GuardedAlternative>,Microsoft.Dafny.AlternativeLoopStmt,Microsoft.Dafny.ResolutionContext)
ResolveCallStmt(Microsoft.Dafny.CallStmt,Microsoft.Dafny.ResolutionContext,Microsoft.Dafny.Type)
ResolveActualParameters(Microsoft.Dafny.ActualBindings,System.Collections.Generic.List`1<Microsoft.Dafny.Formal>,Microsoft.Dafny.IToken,System.Object,Microsoft.Dafny.ResolutionContext,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.TypeParameter,Microsoft.Dafny.Type>,Microsoft.Dafny.Expression)
GetLocationInformation(Microsoft.Dafny.Formal,System.Int32,System.Int32,System.String)
ResolveDotSuffix_Type(Microsoft.Dafny.ExprDotName,Microsoft.Dafny.ResolutionContext,System.Boolean,Microsoft.Dafny.Resolver/ResolveTypeOption,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>)
CreateResolver_IdentifierExpr(Microsoft.Dafny.IToken,System.String,System.Collections.Generic.List`1<Microsoft.Dafny.Type>,Microsoft.Dafny.TopLevelDecl)
ResolveStatement(Microsoft.Dafny.Statement,Microsoft.Dafny.ResolutionContext)
ResolveLoopSpecificationComponents(System.Collections.Generic.List`1<Microsoft.Dafny.AttributedExpression>,Microsoft.Dafny.Specification`1<Microsoft.Dafny.Expression>,Microsoft.Dafny.Specification`1<Microsoft.Dafny.FrameExpression>,Microsoft.Dafny.ResolutionContext)
ResolveParameterDefaultValues(System.Collections.Generic.List`1<Microsoft.Dafny.Formal>,Microsoft.Dafny.ResolutionContext)
ResolveType(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,Microsoft.Dafny.ResolutionContext,Microsoft.Dafny.ResolveTypeOptionEnum,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>)
ResolveType(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,Microsoft.Dafny.ICodeContext,Microsoft.Dafny.ResolveTypeOptionEnum,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>)
ResolveType(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,Microsoft.Dafny.ICodeContext,Microsoft.Dafny.Resolver/ResolveTypeOption,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>)
ResolveType(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,Microsoft.Dafny.ResolutionContext,Microsoft.Dafny.Resolver/ResolveTypeOption,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>)
.ctor(Microsoft.Dafny.Type,Microsoft.Dafny.ExprDotName)
ResolveTypeLenient(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,Microsoft.Dafny.ResolutionContext,Microsoft.Dafny.Resolver/ResolveTypeOption,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>,System.Boolean)
FillInTypeArguments(Microsoft.Dafny.IToken,System.Int32,System.Collections.Generic.List`1<Microsoft.Dafny.Type>,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>,Microsoft.Dafny.Resolver/ResolveTypeOption)
TypeConstraintsIncludeProxy(Microsoft.Dafny.Type,Microsoft.Dafny.TypeProxy)
TypeConstraintsIncludeProxy_Aux(Microsoft.Dafny.Type,Microsoft.Dafny.TypeProxy,System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>)
ResolveTypeRhs(Microsoft.Dafny.TypeRhs,Microsoft.Dafny.Statement,Microsoft.Dafny.ResolutionContext)
ResolveMember(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,System.String,Microsoft.Dafny.NonProxyType&)
PartiallyResolveTypeForMemberSelection(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,System.String,System.Int32)
GetBaseTypeFromProxy(Microsoft.Dafny.TypeProxy,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.TypeProxy,Microsoft.Dafny.Type>)
GetBaseTypeFromProxy_Eq(Microsoft.Dafny.TypeProxy,Microsoft.Dafny.Type,Microsoft.Dafny.Type,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.TypeProxy,Microsoft.Dafny.Type>)
GetBaseTypeFromProxy_EqAux(Microsoft.Dafny.TypeProxy,Microsoft.Dafny.Type,Microsoft.Dafny.Type,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.TypeProxy,Microsoft.Dafny.Type>)
GetRelatedTypeProxies(Microsoft.Dafny.Type,System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>)
JoinOfAllSubtypes(Microsoft.Dafny.Type,Microsoft.Dafny.Type&,System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>)
MeetOfAllSupertypes(Microsoft.Dafny.Type,Microsoft.Dafny.Type&,System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeProxy>,System.Boolean)
CheckVariance(Microsoft.Dafny.Type,Microsoft.Dafny.ICallable,Microsoft.Dafny.TypeParameter/TPVariance,System.Boolean)
ConstrainToIntegerType(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,System.Boolean,Microsoft.Dafny.TypeConstraint/ErrorMsg)
ResolveDatatypeUpdate(Microsoft.Dafny.IToken,Microsoft.Dafny.Expression,Microsoft.Dafny.DatatypeDecl,System.Collections.Generic.List`1<System.Tuple`3<Microsoft.Dafny.IToken,System.String,Microsoft.Dafny.Expression>>,Microsoft.Dafny.ResolutionContext,System.Collections.Generic.List`1<Microsoft.Dafny.MemberDecl>&,System.Collections.Generic.List`1<Microsoft.Dafny.DatatypeCtor>&)
DesugarDatatypeUpdate(Microsoft.Dafny.IToken,Microsoft.Dafny.Expression,Microsoft.Dafny.DatatypeDecl,System.Collections.Generic.List`1<Microsoft.Dafny.DatatypeCtor>,System.Collections.Generic.Dictionary`2<System.String,System.Tuple`3<Microsoft.Dafny.BoundVar,Microsoft.Dafny.IdentifierExpr,Microsoft.Dafny.Expression>>,Microsoft.Dafny.ResolutionContext)
ResolveNameSegment(Microsoft.Dafny.NameSegment,System.Boolean,System.Collections.Generic.List`1<Microsoft.Dafny.ActualBinding>,Microsoft.Dafny.ResolutionContext,System.Boolean,System.Boolean)
ResolveNameSegment(Microsoft.Dafny.NameSegment,System.Boolean,System.Collections.Generic.List`1<Microsoft.Dafny.ActualBinding>,Microsoft.Dafny.ResolutionContext,System.Boolean,System.Boolean,Microsoft.Dafny.ModuleDecl&)
ResolveDatatypeConstructor(Microsoft.Dafny.NameSegment,System.Collections.Generic.List`1<Microsoft.Dafny.ActualBinding>,Microsoft.Dafny.ResolutionContext,System.Boolean,System.Tuple`2<Microsoft.Dafny.DatatypeCtor,System.Boolean>,System.String,Microsoft.Dafny.Expression&,Microsoft.Dafny.Expression&)
ResolveNameSegment_Type(Microsoft.Dafny.NameSegment,Microsoft.Dafny.ResolutionContext,Microsoft.Dafny.Resolver/ResolveTypeOption,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>)
ResolveDotSuffix(Microsoft.Dafny.ExprDotName,System.Boolean,System.Collections.Generic.List`1<Microsoft.Dafny.ActualBinding>,Microsoft.Dafny.ResolutionContext,System.Boolean)
CheckForAmbiguityInShadowedImportedModule(Microsoft.Dafny.ModuleDecl,System.String,Microsoft.Dafny.IToken,System.Boolean,System.Boolean)
NameConflictsWithModuleContents(Microsoft.Dafny.ModuleDecl,System.String,System.Boolean,System.Boolean)
ResolveExprDotCall(Microsoft.Dafny.IToken,Microsoft.Dafny.Expression,Microsoft.Dafny.Type,Microsoft.Dafny.MemberDecl,System.Collections.Generic.List`1<Microsoft.Dafny.ActualBinding>,System.Collections.Generic.List`1<Microsoft.Dafny.Type>,Microsoft.Dafny.ResolutionContext,System.Boolean)
ResolveApplySuffix(Microsoft.Dafny.ApplySuffix,Microsoft.Dafny.ResolutionContext,System.Boolean)
ResolveDatatypeValue(Microsoft.Dafny.ResolutionContext,Microsoft.Dafny.DatatypeValue,Microsoft.Dafny.DatatypeDecl,Microsoft.Dafny.Type,System.Boolean)
ResolveFunctionCallExpr(Microsoft.Dafny.FunctionCallExpr,Microsoft.Dafny.ResolutionContext)
ResolveReceiver(Microsoft.Dafny.Expression,Microsoft.Dafny.ResolutionContext)
ResolveSeqSelectExpr(Microsoft.Dafny.SeqSelectExpr,Microsoft.Dafny.ResolutionContext)
get_Options()
.ctor(Microsoft.Dafny.DafnyOptions)
get_Reporter()
get_TypeConstraintErrorsToBeReported()
RevealedInScope(Microsoft.Dafny.Declaration)
VisibleInScope(Microsoft.Dafny.Declaration)
FreshTempVarName(System.String,Microsoft.Dafny.ICodeContext)
Create(Microsoft.Dafny.ModuleDefinition,Thing,Thing,System.Collections.Generic.IEqualityComparer`1<Thing>,System.Collections.Generic.ISet`1<Thing>&)
Name(System.Collections.Generic.ISet`1<Thing>,System.Func`2<Thing,System.String>)
ModuleNames(Microsoft.Dafny.Resolver/IAmbiguousThing`1<Thing>,System.Func`2<Thing,System.String>)
Create(Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.TopLevelDecl,Microsoft.Dafny.TopLevelDecl)
Equals(Microsoft.Dafny.TopLevelDecl,Microsoft.Dafny.TopLevelDecl)
GetHashCode(Microsoft.Dafny.TopLevelDecl)
get_WhatKind()
.ctor(Microsoft.Dafny.ModuleDefinition,System.String,System.Collections.Generic.ISet`1<Microsoft.Dafny.TopLevelDecl>)
Microsoft.Dafny.Resolver.IAmbiguousThing<Microsoft.Dafny.TopLevelDecl>.get_Pool()
ModuleNames()
Create(Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.MemberDecl,Microsoft.Dafny.MemberDecl)
Equals(Microsoft.Dafny.MemberDecl,Microsoft.Dafny.MemberDecl)
GetHashCode(Microsoft.Dafny.MemberDecl)
get_WhatKind()
.ctor(Microsoft.Dafny.ModuleDefinition,System.String,System.Collections.Generic.ISet`1<Microsoft.Dafny.MemberDecl>)
Microsoft.Dafny.Resolver.IAmbiguousThing<Microsoft.Dafny.MemberDecl>.get_Pool()
ModuleNames()
.ctor(Microsoft.Dafny.Program)
AddRotateMember(Microsoft.Dafny.ValuetypeDecl,System.String,Microsoft.Dafny.Type)
ObjectInvariant()
AsValuetypeDecl(Microsoft.Dafny.Type)
CheckDupModuleNames(Microsoft.Dafny.Program)
ResolveProgram(Microsoft.Dafny.Program)
ResolveValuetypeDecls()
ResolveModuleDefinition(Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.ModuleSignature,System.Boolean)
ResolveModuleExport(Microsoft.Dafny.LiteralModuleDecl,Microsoft.Dafny.ModuleSignature)
CheckModuleExportConsistency(Microsoft.Dafny.ModuleDefinition)
.ctor(Microsoft.Dafny.Resolver/ModuleBindings)
BindName(System.String,Microsoft.Dafny.ModuleDecl,Microsoft.Dafny.Resolver/ModuleBindings)
TryLookup(Microsoft.Dafny.IToken,Microsoft.Dafny.ModuleDecl&)
TryLookupFilter(Microsoft.Dafny.IToken,Microsoft.Dafny.ModuleDecl&,System.Func`2<Microsoft.Dafny.ModuleDecl,System.Boolean>)
get_ModuleList()
SubBindings(System.String)
BindModuleNames(Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.Resolver/ModuleBindings)
ShortenPrefix(System.Tuple`2<System.Collections.Generic.List`1<Microsoft.Dafny.IToken>,Microsoft.Dafny.LiteralModuleDecl>)
BindModuleName_LiteralModuleDecl(Microsoft.Dafny.LiteralModuleDecl,System.Collections.Generic.List`1<System.Tuple`2<System.Collections.Generic.List`1<Microsoft.Dafny.IToken>,Microsoft.Dafny.LiteralModuleDecl>>,Microsoft.Dafny.Resolver/ModuleBindings)
ResolveQualifiedModuleIdRootRefines(Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.Resolver/ModuleBindings,Microsoft.Dafny.ModuleQualifiedId,Microsoft.Dafny.ModuleDecl&)
ResolveQualifiedModuleIdRootImport(Microsoft.Dafny.AliasModuleDecl,Microsoft.Dafny.Resolver/ModuleBindings,Microsoft.Dafny.ModuleQualifiedId,Microsoft.Dafny.ModuleDecl&)
ResolveQualifiedModuleIdRootAbstract(Microsoft.Dafny.AbstractModuleDecl,Microsoft.Dafny.Resolver/ModuleBindings,Microsoft.Dafny.ModuleQualifiedId,Microsoft.Dafny.ModuleDecl&)
ProcessDependenciesDefinition(Microsoft.Dafny.ModuleDecl,Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.Resolver/ModuleBindings,Microsoft.Dafny.Graph`1<Microsoft.Dafny.ModuleDecl>)
ProcessDependencies(Microsoft.Dafny.ModuleDecl,Microsoft.Dafny.Resolver/ModuleBindings,Microsoft.Dafny.Graph`1<Microsoft.Dafny.ModuleDecl>)
ModuleNotFoundErrorMessage(System.Int32,System.Collections.Generic.List`1<Microsoft.Dafny.Name>,System.String)
EquivIfPresent(System.Collections.Generic.Dictionary`2<T1,T2>,T1,T2)
MergeSignature(Microsoft.Dafny.ModuleSignature,Microsoft.Dafny.ModuleSignature)
ResolveOpenedImports(Microsoft.Dafny.ModuleSignature,Microsoft.Dafny.ModuleDefinition,System.Boolean,Microsoft.Dafny.Resolver)
ResolveAlias(Microsoft.Dafny.TopLevelDecl)
ResolveOpenedImportsWorker(Microsoft.Dafny.ModuleSignature,Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.ModuleDecl,System.Collections.Generic.HashSet`1<Microsoft.Dafny.ModuleSignature>,System.Boolean,Microsoft.Dafny.TopLevelDecl&)
RegisterTopLevelDecls(Microsoft.Dafny.ModuleDefinition,System.Boolean)
RegisterMembers(Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.TopLevelDeclWithMembers,System.Collections.Generic.Dictionary`2<System.String,Microsoft.Dafny.MemberDecl>)
RegisterByMethod(Microsoft.Dafny.Function,Microsoft.Dafny.TopLevelDeclWithMembers)
MakeAbstractSignature(Microsoft.Dafny.ModuleSignature,System.String,System.Int32,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.ModuleSignature>,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.ModuleDefinition>)
CloneDeclaration(Microsoft.Dafny.VisibilityScope,Microsoft.Dafny.TopLevelDecl,Microsoft.Dafny.ModuleDefinition,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.ModuleSignature>,System.String,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.ModuleDefinition>)
ResolveModuleQualifiedId(Microsoft.Dafny.ModuleDecl,Microsoft.Dafny.ModuleQualifiedId,Microsoft.Dafny.ErrorReporter)
ResolveExport(Microsoft.Dafny.ModuleDecl,Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.ModuleQualifiedId,System.Collections.Generic.List`1<Microsoft.Dafny.IToken>,Microsoft.Dafny.ModuleSignature&,Microsoft.Dafny.ErrorReporter)
RevealAllInScope(System.Collections.Generic.List`1<Microsoft.Dafny.TopLevelDecl>,Microsoft.Dafny.VisibilityScope)
ResolveTopLevelDecls_Signatures(Microsoft.Dafny.ModuleDefinition,Microsoft.Dafny.ModuleSignature,System.Collections.Generic.List`1<Microsoft.Dafny.TopLevelDecl>,Microsoft.Dafny.Graph`1<Microsoft.Dafny.IndDatatypeDecl>,Microsoft.Dafny.Graph`1<Microsoft.Dafny.CoDatatypeDecl>)
.cctor()
ResolveTopLevelDecls_Core(System.Collections.Generic.List`1<Microsoft.Dafny.TopLevelDecl>,Microsoft.Dafny.Graph`1<Microsoft.Dafny.IndDatatypeDecl>,Microsoft.Dafny.Graph`1<Microsoft.Dafny.CoDatatypeDecl>,System.String,System.Boolean)
FillInPostConditionsAndBodiesOfPrefixLemmas(System.Collections.Generic.List`1<Microsoft.Dafny.TopLevelDecl>)
CheckIsOkayWithoutRHS(Microsoft.Dafny.ConstantField)
ResolveClassMembers_Pass1(Microsoft.Dafny.TopLevelDeclWithMembers)
CheckForUnnecessaryEqualitySupportDeclarations(Microsoft.Dafny.MemberDecl,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>)
CheckParameterDefaultValuesAreCompilable(System.Collections.Generic.List`1<Microsoft.Dafny.Formal>,Microsoft.Dafny.ICodeContext)
ReportCallGraphCycleError(Microsoft.Dafny.ICallable,System.String)
ReportCycleError(System.Collections.Generic.List`1<X>,System.Func`2<X,Microsoft.Dafny.IToken>,System.Func`2<X,System.String>,System.String)
MaxBV(Microsoft.Dafny.Type)
MaxBV(System.Int32)
FigureOutNativeType(Microsoft.Dafny.NewtypeDecl)
CheckOlderParameters(Microsoft.Dafny.Function)
CheckExpression(Microsoft.Dafny.Expression,Microsoft.Dafny.Resolver,Microsoft.Dafny.ICodeContext)
CheckExpression(Microsoft.Dafny.Statement,Microsoft.Dafny.Resolver,Microsoft.Dafny.ICodeContext)
.ctor(Microsoft.Dafny.Resolver,Microsoft.Dafny.ICodeContext)
VisitOneExpr(Microsoft.Dafny.Expression)
VisitOneStmt(Microsoft.Dafny.Statement)
CheckForFuelAdjustments(Microsoft.Dafny.IToken,Microsoft.Dafny.Attributes,Microsoft.Dafny.ModuleDefinition)
.ctor(Microsoft.Dafny.ModuleDefinition)
.ctor(Microsoft.Dafny.Resolver)
VisitOneStmt(Microsoft.Dafny.Statement,Microsoft.Dafny.Resolver/FuelAdjustment_Context&)
Invert(Microsoft.Dafny.Resolver/CallingPosition)
.ctor(Microsoft.Dafny.Resolver,System.Boolean,System.Boolean)
VisitOneExpr(Microsoft.Dafny.Expression,Microsoft.Dafny.Resolver/CallingPosition&)
KNatMismatchError(Microsoft.Dafny.IToken,System.String,Microsoft.Dafny.ExtremePredicate/KType,Microsoft.Dafny.ExtremePredicate/KType)
.ctor(Microsoft.Dafny.Resolver,Microsoft.Dafny.ExtremePredicate)
VisitOneExpr(Microsoft.Dafny.Expression,Microsoft.Dafny.Resolver/CallingPosition&)
VisitOneStmt(Microsoft.Dafny.Statement,Microsoft.Dafny.Resolver/CallingPosition&)
ExtremePredicateChecks(Microsoft.Dafny.Expression,Microsoft.Dafny.ExtremePredicate,Microsoft.Dafny.Resolver/CallingPosition)
.ctor(Microsoft.Dafny.Resolver,Microsoft.Dafny.ExtremeLemma)
VisitOneStmt(Microsoft.Dafny.Statement)
VisitOneExpr(Microsoft.Dafny.Expression)
ExtremeLemmaChecks(Microsoft.Dafny.Statement,Microsoft.Dafny.ExtremeLemma)
ExtremeLemmaChecks(Microsoft.Dafny.Expression,Microsoft.Dafny.ExtremeLemma)
CheckTypeCharacteristics_Stmt(Microsoft.Dafny.Statement,System.Boolean)
CheckTypeCharacteristics_Expr(Microsoft.Dafny.Expression,System.Boolean)
CheckTypeCharacteristics_Type(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,System.Boolean)
.ctor(Microsoft.Dafny.Resolver)
VisitOneStmt(Microsoft.Dafny.Statement,System.Boolean&)
VisitOneExpr(Microsoft.Dafny.Expression,System.Boolean&)
VisitType(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,System.Boolean)
CheckTypeInstantiation(Microsoft.Dafny.IToken,System.String,System.String,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>,System.Collections.Generic.List`1<Microsoft.Dafny.Type>,System.Boolean)
CheckCharacteristics(Microsoft.Dafny.TypeParameter/TypeParameterCharacteristics,Microsoft.Dafny.Type,System.Boolean,System.String&,System.String&)
TypeEqualityErrorMessageHint(Microsoft.Dafny.Type)
CanCompareWith(Microsoft.Dafny.Expression)
ComputeGhostInterest(Microsoft.Dafny.Statement,System.Boolean,System.String,Microsoft.Dafny.ICodeContext)
.ctor(Microsoft.Dafny.Resolver,Microsoft.Dafny.ICallable)
VisitOneStmt(Microsoft.Dafny.Statement)
.ctor(Microsoft.Dafny.Resolver)
VisitOneStmt(Microsoft.Dafny.Statement)
.ctor(Microsoft.Dafny.Resolver)
CheckInit(System.Collections.Generic.List`1<Microsoft.Dafny.Statement>)
CheckInit(Microsoft.Dafny.Statement)
VisitExpr(Microsoft.Dafny.Expression)
VisitOneExpr(Microsoft.Dafny.Expression,System.Int32&)
LiberalRHSVisit(Microsoft.Dafny.Expression)
IsThisDotField(Microsoft.Dafny.MemberSelectExpr)
IsCollectionOperator(Microsoft.Dafny.BinaryExpr/ResolvedOpcode)
InferRequiredEqualitySupport(Microsoft.Dafny.TypeParameter,Microsoft.Dafny.Type)
ResolveParentTraitTypes(Microsoft.Dafny.TopLevelDeclWithMembers,Microsoft.Dafny.Graph`1<Microsoft.Dafny.TopLevelDeclWithMembers>)
RegisterInheritedMembers(Microsoft.Dafny.TopLevelDeclWithMembers)
ResolveClassMemberTypes(Microsoft.Dafny.TopLevelDeclWithMembers)
InheritedTraitMembers(Microsoft.Dafny.TopLevelDeclWithMembers)
CheckOverride_FunctionParameters(Microsoft.Dafny.Function,Microsoft.Dafny.Function,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.TypeParameter,Microsoft.Dafny.Type>)
CheckOverride_MethodParameters(Microsoft.Dafny.Method,Microsoft.Dafny.Method,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.TypeParameter,Microsoft.Dafny.Type>)
CheckOverride_TypeParameters(Microsoft.Dafny.IToken,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>,System.Collections.Generic.List`1<Microsoft.Dafny.TypeParameter>,System.String,System.String,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.TypeParameter,Microsoft.Dafny.Type>)
CheckOverride_ResolvedParameters(Microsoft.Dafny.IToken,System.Collections.Generic.List`1<Microsoft.Dafny.Formal>,System.Collections.Generic.List`1<Microsoft.Dafny.Formal>,System.String,System.String,System.String,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.TypeParameter,Microsoft.Dafny.Type>)
SccStratosphereCheck(Microsoft.Dafny.IndDatatypeDecl,Microsoft.Dafny.Graph`1<Microsoft.Dafny.IndDatatypeDecl>)
ComputeGroundingCtor(Microsoft.Dafny.IndDatatypeDecl)
CheckCanBeConstructed(Microsoft.Dafny.Type,System.Collections.Generic.ISet`1<Microsoft.Dafny.TypeParameter>)
DetermineEqualitySupport(Microsoft.Dafny.IndDatatypeDecl,Microsoft.Dafny.Graph`1<Microsoft.Dafny.IndDatatypeDecl>)
IsRecognizedAttribute(Microsoft.Dafny.UserSuppliedAttributes,Microsoft.Dafny.IAttributeBearingDeclaration)
ScopePushAndReport(Microsoft.Dafny.Scope`1<Microsoft.Dafny.IVariable>,Microsoft.Dafny.IVariable,System.String)
ScopePushAndReport(Microsoft.Dafny.Scope`1<Thing>,System.String,Thing,Microsoft.Dafny.IToken,System.String)
ResolveFunctionSignature(Microsoft.Dafny.Function)
DisallowNonGhostFieldSpecifiers(Microsoft.Dafny.FrameExpression)
ResolveMethodSignature(Microsoft.Dafny.Method)
ResolveIteratorSignature(Microsoft.Dafny.IteratorDecl)
ObjectInvariant()
.ctor(Microsoft.Dafny.ResolveTypeOptionEnum)
.ctor(Microsoft.Dafny.TypeParameter/ParentType)
ResolvedArrayType(Microsoft.Dafny.IToken,System.Int32,Microsoft.Dafny.Type,Microsoft.Dafny.ResolutionContext,System.Boolean)
FillInDefaultLoopDecreases(Microsoft.Dafny.LoopStmt,Microsoft.Dafny.Expression,System.Collections.Generic.List`1<Microsoft.Dafny.Expression>,Microsoft.Dafny.ICallable)
VarDotMethod(Microsoft.Dafny.IToken,System.String,System.String)
makeTemp(System.String,Microsoft.Dafny.AssignOrReturnStmt,Microsoft.Dafny.ResolutionContext,Microsoft.Dafny.Expression)
EnsureSupportsErrorHandling(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,System.Boolean,System.Boolean)
CheckLocalityUpdates(Microsoft.Dafny.Statement,System.Collections.Generic.ISet`1<Microsoft.Dafny.LocalVariable>,System.String)
CheckLocalityUpdatesLhs(Microsoft.Dafny.Expression,System.Collections.Generic.ISet`1<Microsoft.Dafny.LocalVariable>,System.String)
.ctor(Microsoft.Dafny.Type,Microsoft.Dafny.Type,System.String)
ToString()
FindAllMembers(Microsoft.Dafny.ClassDecl,System.String,System.Collections.Generic.ISet`1<Microsoft.Dafny.MemberDecl>)
GetThisType(Microsoft.Dafny.IToken,Microsoft.Dafny.TopLevelDeclWithMembers)
GetReceiverType(Microsoft.Dafny.IToken,Microsoft.Dafny.MemberDecl)
ResolveDominatingLabelInExpr(Microsoft.Dafny.IToken,System.String,System.String,Microsoft.Dafny.ResolutionContext)
VarDotFunction(Microsoft.Dafny.IToken,System.String,System.String)
LetPatIn(Microsoft.Dafny.IToken,Microsoft.Dafny.CasePattern`1<Microsoft.Dafny.BoundVar>,Microsoft.Dafny.Expression,Microsoft.Dafny.Expression)
LetVarIn(Microsoft.Dafny.IToken,System.String,Microsoft.Dafny.Type,Microsoft.Dafny.Expression,Microsoft.Dafny.Expression)
ResolveLetOrFailExpr(Microsoft.Dafny.LetOrFailExpr,Microsoft.Dafny.ResolutionContext)
SelectAppropriateArrowTypeForFunction(Microsoft.Dafny.Function,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.TypeParameter,Microsoft.Dafny.Type>,Microsoft.Dafny.BuiltIns)
SelectAppropriateArrowType(Microsoft.Dafny.IToken,System.Collections.Generic.List`1<Microsoft.Dafny.Type>,Microsoft.Dafny.Type,System.Boolean,System.Boolean,Microsoft.Dafny.BuiltIns)
ConstrainToIntegerType(Microsoft.Dafny.Expression,System.Boolean,System.String)
ResolveNestedMatchExpr(Microsoft.Dafny.NestedMatchExpr,Microsoft.Dafny.ResolutionContext)
ResolveCasePattern(Microsoft.Dafny.CasePattern`1<VT>,Microsoft.Dafny.Type,Microsoft.Dafny.ResolutionContext)
FillInDefaultValueExpressions()
FillInDefaultValueExpression(Microsoft.Dafny.DefaultValueExpression,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.DefaultValueExpression,Microsoft.Dafny.Resolver/WorkProgress>)
.ctor(Microsoft.Dafny.Resolver,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.DefaultValueExpression,Microsoft.Dafny.Resolver/WorkProgress>,Microsoft.Dafny.Expression,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.IVariable,Microsoft.Dafny.Expression>,System.Collections.Generic.Dictionary`2<Microsoft.Dafny.TypeParameter,Microsoft.Dafny.Type>)
Substitute(Microsoft.Dafny.Expression)
BuildTypeArgumentSubstitute(System.Collections.Generic.Dictionary`2<Microsoft.Dafny.TypeParameter,Microsoft.Dafny.Type>,Microsoft.Dafny.Type)
AddParentTypeParameterSubstitutions(System.Collections.Generic.Dictionary`2<Microsoft.Dafny.TypeParameter,Microsoft.Dafny.Type>,Microsoft.Dafny.Type)
GhostPrefix(System.Boolean)
GetSignatureExt(Microsoft.Dafny.ModuleSignature,System.Boolean)
GetSignature(Microsoft.Dafny.ModuleSignature)
GetImpliedTypeConstraint(Microsoft.Dafny.IVariable,Microsoft.Dafny.Type)
GetImpliedTypeConstraint(Microsoft.Dafny.Expression,Microsoft.Dafny.Type)
FreeVariables(Microsoft.Dafny.Expression)
.cctor()
get_Msg()
.ctor(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,Microsoft.Dafny.Type)
ResolveOp(Microsoft.Dafny.BinaryExpr/Opcode,Microsoft.Dafny.Type,Microsoft.Dafny.Type)
CollectFriendlyCallsInExtremeLemmaSpecification(Microsoft.Dafny.Expression,System.Boolean,System.Collections.Generic.ISet`1<Microsoft.Dafny.Expression>,System.Boolean,Microsoft.Dafny.ExtremeLemma)
.ctor(Microsoft.Dafny.Resolver,System.Collections.Generic.ISet`1<Microsoft.Dafny.Expression>,System.Boolean,Microsoft.Dafny.ExtremeLemma)
VisitOneExpr(Microsoft.Dafny.Expression,Microsoft.Dafny.Resolver/CallingPosition&)
get_IsPrefixPredicate()
get_IsExtremePredicate()
get_IsPrefixDeclaration()
.ctor(Microsoft.Dafny.IASTVisitorContext)
Microsoft.Dafny.IASTVisitorContext.get_EnclosingModule()
get_reporter()
.ctor(Microsoft.Dafny.Resolver)
GetContext(Microsoft.Dafny.IASTVisitorContext,System.Boolean)
VisitOneDeclaration(Microsoft.Dafny.TopLevelDecl)
VisitField(Microsoft.Dafny.Field)
VisitOneStatement(Microsoft.Dafny.Statement,Microsoft.Dafny.Resolver/TypeInferenceCheckingContext)
PostVisitOneStatement(Microsoft.Dafny.Statement,Microsoft.Dafny.Resolver/TypeInferenceCheckingContext)
PostVisitOneExpression(Microsoft.Dafny.Expression,Microsoft.Dafny.Resolver/TypeInferenceCheckingContext)
VisitExtendedPattern(Microsoft.Dafny.ExtendedPattern,Microsoft.Dafny.Resolver/TypeInferenceCheckingContext)
IsDetermined(Microsoft.Dafny.Type)
CheckTypeIsDetermined(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,System.String)
CheckTypeArgsContainNoOrdinal(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,Microsoft.Dafny.Resolver/TypeInferenceCheckingContext)
CheckContainsNoOrdinal(Microsoft.Dafny.IToken,Microsoft.Dafny.Type,System.String)